@ui5/builder 3.0.0-alpha.5 → 3.0.0-alpha.8

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 (50) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/index.js +0 -39
  3. package/lib/lbt/analyzer/JSModuleAnalyzer.js +13 -2
  4. package/lib/lbt/bundle/Builder.js +19 -49
  5. package/lib/lbt/resources/LocatorResource.js +1 -1
  6. package/lib/lbt/resources/ResourceCollector.js +22 -15
  7. package/lib/lbt/resources/ResourceInfoList.js +0 -1
  8. package/lib/lbt/resources/ResourcePool.js +7 -6
  9. package/lib/lbt/utils/escapePropertiesFile.js +3 -6
  10. package/lib/processors/bundlers/moduleBundler.js +2 -3
  11. package/lib/processors/jsdoc/lib/createIndexFiles.js +1 -1
  12. package/lib/processors/jsdoc/lib/transformApiJson.js +20 -20
  13. package/lib/processors/jsdoc/lib/ui5/plugin.js +111 -6
  14. package/lib/processors/jsdoc/lib/ui5/template/publish.js +112 -91
  15. package/lib/processors/jsdoc/lib/ui5/template/utils/versionUtil.js +1 -1
  16. package/lib/processors/manifestCreator.js +8 -45
  17. package/lib/tasks/TaskUtil.js +82 -17
  18. package/lib/tasks/bundlers/generateComponentPreload.js +14 -14
  19. package/lib/tasks/bundlers/generateFlexChangesBundle.js +6 -2
  20. package/lib/tasks/bundlers/generateLibraryPreload.js +84 -91
  21. package/lib/tasks/bundlers/generateManifestBundle.js +8 -10
  22. package/lib/tasks/bundlers/generateStandaloneAppBundle.js +7 -2
  23. package/lib/tasks/bundlers/utils/createModuleNameMapping.js +3 -2
  24. package/lib/tasks/generateCachebusterInfo.js +7 -3
  25. package/lib/tasks/generateLibraryManifest.js +6 -8
  26. package/lib/tasks/generateResourcesJson.js +1 -1
  27. package/lib/tasks/generateThemeDesignerResources.js +8 -2
  28. package/lib/tasks/generateVersionInfo.js +5 -5
  29. package/lib/tasks/taskRepository.js +1 -13
  30. package/lib/tasks/transformBootstrapHtml.js +6 -1
  31. package/package.json +6 -7
  32. package/lib/builder/BuildContext.js +0 -60
  33. package/lib/builder/ProjectBuildContext.js +0 -61
  34. package/lib/builder/builder.js +0 -425
  35. package/lib/types/AbstractBuilder.js +0 -270
  36. package/lib/types/AbstractFormatter.js +0 -66
  37. package/lib/types/AbstractUi5Formatter.js +0 -95
  38. package/lib/types/application/ApplicationBuilder.js +0 -211
  39. package/lib/types/application/ApplicationFormatter.js +0 -227
  40. package/lib/types/application/applicationType.js +0 -15
  41. package/lib/types/library/LibraryBuilder.js +0 -232
  42. package/lib/types/library/LibraryFormatter.js +0 -519
  43. package/lib/types/library/libraryType.js +0 -15
  44. package/lib/types/module/ModuleBuilder.js +0 -7
  45. package/lib/types/module/ModuleFormatter.js +0 -54
  46. package/lib/types/module/moduleType.js +0 -15
  47. package/lib/types/themeLibrary/ThemeLibraryBuilder.js +0 -64
  48. package/lib/types/themeLibrary/ThemeLibraryFormatter.js +0 -90
  49. package/lib/types/themeLibrary/themeLibraryType.js +0 -15
  50. package/lib/types/typeRepository.js +0 -46
@@ -19,9 +19,15 @@ class TaskUtil {
19
19
  * @public
20
20
  * @typedef {object} module:@ui5/builder.tasks.TaskUtil~StandardBuildTags
21
21
  * @property {string} OmitFromBuildResult
22
- * Setting this tag to true for a resource will prevent it from being written to the build target
22
+ * Setting this tag to true will prevent the resource from being written to the build target directory
23
23
  * @property {string} IsBundle
24
24
  * This tag identifies resources that contain (i.e. bundle) multiple other resources
25
+ * @property {string} IsDebugVariant
26
+ * This tag identifies resources that are a debug variant (typically named with a "-dbg" suffix)
27
+ * of another resource. This tag is part of the build manifest.
28
+ * @property {string} HasDebugVariant
29
+ * This tag identifies resources for which a debug variant has been created.
30
+ * This tag is part of the build manifest.
25
31
  */
26
32
 
27
33
  /**
@@ -34,12 +40,22 @@ class TaskUtil {
34
40
  */
35
41
  constructor({projectBuildContext}) {
36
42
  this._projectBuildContext = projectBuildContext;
37
-
38
43
  /**
39
44
  * @member {module:@ui5/builder.tasks.TaskUtil~StandardBuildTags}
40
45
  * @public
41
46
  */
42
- this.STANDARD_TAGS = this._projectBuildContext.STANDARD_TAGS;
47
+ this.STANDARD_TAGS = Object.freeze({
48
+ // "Project" tags:
49
+ // Will be stored on project instance and are hence part of the build manifest
50
+ IsDebugVariant: "ui5:IsDebugVariant",
51
+ HasDebugVariant: "ui5:HasDebugVariant",
52
+
53
+ // "Build" tags:
54
+ // Will be stored on the project build context
55
+ // They are only available to the build tasks of a single project
56
+ OmitFromBuildResult: "ui5:OmitFromBuildResult",
57
+ IsBundle: "ui5:IsBundle"
58
+ });
43
59
  }
44
60
 
45
61
  /**
@@ -51,14 +67,20 @@ class TaskUtil {
51
67
  * This method is only available to custom task extensions defining
52
68
  * <b>Specification Version 2.2 and above</b>.
53
69
  *
54
- * @param {string|module:@ui5/fs.Resource} resourcePath Path or resource-instance the tag should be stored for
70
+ * @param {module:@ui5/fs.Resource} resource Resource-instance the tag should be stored for
55
71
  * @param {string} tag Name of the tag.
56
72
  * Currently only the [STANDARD_TAGS]{@link module:@ui5/builder.tasks.TaskUtil#STANDARD_TAGS} are allowed
57
73
  * @param {string|boolean|integer} [value=true] Tag value. Must be primitive
58
74
  * @public
59
75
  */
60
- setTag(resourcePath, tag, value) {
61
- return this._projectBuildContext.getResourceTagCollection().setTag(resourcePath, tag, value);
76
+ setTag(resource, tag, value) {
77
+ if (typeof resource === "string") {
78
+ throw new Error("Deprecated parameter: " +
79
+ "Since UI5 Tooling 3.0, #setTag requires a resource instance. Strings are no longer accepted");
80
+ }
81
+
82
+ const collection = this._projectBuildContext.getResourceTagCollection(resource, tag);
83
+ return collection.setTag(resource, tag, value);
62
84
  }
63
85
 
64
86
  /**
@@ -68,14 +90,19 @@ class TaskUtil {
68
90
  * This method is only available to custom task extensions defining
69
91
  * <b>Specification Version 2.2 and above</b>.
70
92
  *
71
- * @param {string|module:@ui5/fs.Resource} resourcePath Path or resource-instance the tag should be retrieved for
93
+ * @param {module:@ui5/fs.Resource} resource Resource-instance the tag should be retrieved for
72
94
  * @param {string} tag Name of the tag
73
95
  * @returns {string|boolean|integer|undefined} Tag value for the given resource.
74
96
  * <code>undefined</code> if no value is available
75
97
  * @public
76
98
  */
77
- getTag(resourcePath, tag) {
78
- return this._projectBuildContext.getResourceTagCollection().getTag(resourcePath, tag);
99
+ getTag(resource, tag) {
100
+ if (typeof resource === "string") {
101
+ throw new Error("Deprecated parameter: " +
102
+ "Since UI5 Tooling 3.0, #getTag requires a resource instance. Strings are no longer accepted");
103
+ }
104
+ const collection = this._projectBuildContext.getResourceTagCollection(resource, tag);
105
+ return collection.getTag(resource, tag);
79
106
  }
80
107
 
81
108
  /**
@@ -86,12 +113,17 @@ class TaskUtil {
86
113
  * This method is only available to custom task extensions defining
87
114
  * <b>Specification Version 2.2 and above</b>.
88
115
  *
89
- * @param {string|module:@ui5/fs.Resource} resourcePath Path or resource-instance the tag should be cleared for
116
+ * @param {module:@ui5/fs.Resource} resource Resource-instance the tag should be cleared for
90
117
  * @param {string} tag Tag
91
118
  * @public
92
119
  */
93
- clearTag(resourcePath, tag) {
94
- return this._projectBuildContext.getResourceTagCollection().clearTag(resourcePath, tag);
120
+ clearTag(resource, tag) {
121
+ if (typeof resource === "string") {
122
+ throw new Error("Deprecated parameter: " +
123
+ "Since UI5 Tooling 3.0, #clearTag requires a resource instance. Strings are no longer accepted");
124
+ }
125
+ const collection = this._projectBuildContext.getResourceTagCollection(resource, tag);
126
+ return collection.clearTag(resource, tag);
95
127
  }
96
128
 
97
129
  /**
@@ -136,6 +168,22 @@ class TaskUtil {
136
168
  return this._projectBuildContext.registerCleanupTask(callback);
137
169
  }
138
170
 
171
+ /**
172
+ * Retrieve a single project from the dependency graph
173
+ *
174
+ * </br></br>
175
+ * This method is only available to custom task extensions defining
176
+ * <b>Specification Version 3.0 and above</b>.
177
+ *
178
+ * @param {string} projectName Name of the project to retrieve
179
+ * @returns {module:@ui5/project.specifications.Project|undefined}
180
+ * project instance or undefined if the project is unknown to the graph
181
+ * @public
182
+ */
183
+ getProject(projectName) {
184
+ return this._projectBuildContext.getProject(projectName);
185
+ }
186
+
139
187
  /**
140
188
  * Get an interface to an instance of this class that only provides those functions
141
189
  * that are supported by the given custom task extension specification version.
@@ -150,12 +198,10 @@ class TaskUtil {
150
198
 
151
199
  const baseInterface = {
152
200
  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
201
  };
202
+ bindFunctions(this, baseInterface, [
203
+ "setTag", "clearTag", "getTag", "isRootProject", "registerCleanupTask"
204
+ ]);
159
205
  switch (specVersion) {
160
206
  case "2.2":
161
207
  case "2.3":
@@ -163,10 +209,29 @@ class TaskUtil {
163
209
  case "2.5":
164
210
  case "2.6":
165
211
  return baseInterface;
212
+ case "3.0":
213
+ baseInterface.getProject = (projectName) => {
214
+ const project = this.getProject(projectName);
215
+ const baseProjectInterface = {};
216
+ bindFunctions(project, baseProjectInterface, [
217
+ "getName", "getVersion", "getNamespace"
218
+ ]);
219
+ switch (specVersion) {
220
+ case "3.0":
221
+ return baseProjectInterface;
222
+ }
223
+ };
224
+ return baseInterface;
166
225
  default:
167
226
  throw new Error(`TaskUtil: Unknown or unsupported Specification Version ${specVersion}`);
168
227
  }
169
228
  }
170
229
  }
171
230
 
231
+ function bindFunctions(sourceObject, targetObject, funcNames) {
232
+ funcNames.forEach((funcName) => {
233
+ targetObject[funcName] = sourceObject[funcName].bind(sourceObject);
234
+ });
235
+ }
236
+
172
237
  module.exports = TaskUtil;
@@ -1,7 +1,6 @@
1
1
  const path = require("path");
2
2
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
3
3
  const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateComponentPreload");
4
- const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
5
4
  const {negateFilters} = require("../../lbt/resources/ResourceFilterList");
6
5
 
7
6
  /**
@@ -11,7 +10,6 @@ const {negateFilters} = require("../../lbt/resources/ResourceFilterList");
11
10
  * @alias module:@ui5/builder.tasks.generateComponentPreload
12
11
  * @param {object} parameters Parameters
13
12
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
14
- * @param {module:@ui5/fs.AbstractReader} parameters.dependencies Reader or Collection to read dependency files
15
13
  * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
16
14
  * @param {object} parameters.options Options
17
15
  * @param {string} parameters.options.projectName Project name
@@ -23,32 +21,28 @@ const {negateFilters} = require("../../lbt/resources/ResourceFilterList");
23
21
  * inclusion overrides an earlier exclusion, and vice versa.
24
22
  * @param {string[]} [parameters.options.paths] Array of paths (or glob patterns) for component files
25
23
  * @param {string[]} [parameters.options.namespaces] Array of component namespaces
24
+ * @param {string[]} [parameters.options.skipBundles] Names of bundles that should not be created
26
25
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
27
26
  */
28
27
  module.exports = function({
29
- workspace, dependencies, taskUtil, options: {projectName, paths, namespaces, excludes = []}
28
+ workspace, taskUtil, options: {projectName, paths, namespaces, skipBundles = [], excludes = []}
30
29
  }) {
31
- let combo = new ReaderCollectionPrioritized({
32
- name: `generateComponentPreload - prioritize workspace over dependencies: ${projectName}`,
33
- readers: [workspace, dependencies]
34
- });
35
-
30
+ let nonDbgWorkspace = workspace;
36
31
  if (taskUtil) {
37
- combo = combo.filter(function(resource) {
32
+ nonDbgWorkspace = workspace.filter(function(resource) {
38
33
  // Remove any debug variants
39
34
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant);
40
35
  });
41
36
  }
42
37
 
43
- // TODO 3.0: Limit to workspace resources?
44
- return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}")
38
+ return nonDbgWorkspace.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}")
45
39
  .then(async (resources) => {
46
40
  let allNamespaces = [];
47
41
  if (paths) {
48
42
  allNamespaces = await Promise.all(paths.map(async (componentPath) => {
49
43
  const globPath = "/resources/" + componentPath;
50
44
  log.verbose(`Globbing for Components directories with configured path ${globPath}...`);
51
- const components = await combo.byGlob(globPath); // TODO 3.0: Limit to workspace resources?
45
+ const components = await nonDbgWorkspace.byGlob(globPath);
52
46
  return components.map((component) => {
53
47
  const compDir = path.dirname(component.getPath()).replace(/^\/resources\//i, "");
54
48
  log.verbose(`Found component namespace ${compDir}`);
@@ -72,6 +66,12 @@ module.exports = function({
72
66
  const unusedFilterExcludes = new Set(allFilterExcludes);
73
67
 
74
68
  const bundleDefinitions = allNamespaces.map((namespace) => {
69
+ const bundleName = `${namespace}/Component-preload.js`;
70
+ if (skipBundles.includes(bundleName)) {
71
+ log.verbose(`Skipping generation of bundle ${bundleName}`);
72
+ return null;
73
+ }
74
+
75
75
  const filters = [
76
76
  `${namespace}/`,
77
77
  `${namespace}/**/manifest.json`,
@@ -101,7 +101,7 @@ module.exports = function({
101
101
  });
102
102
 
103
103
  return {
104
- name: `${namespace}/Component-preload.js`,
104
+ name: bundleName,
105
105
  defaultFileTypes: [
106
106
  ".js",
107
107
  ".control.xml",
@@ -134,7 +134,7 @@ module.exports = function({
134
134
  });
135
135
  }
136
136
 
137
- return Promise.all(bundleDefinitions.map((bundleDefinition) => {
137
+ return Promise.all(bundleDefinitions.filter(Boolean).map((bundleDefinition) => {
138
138
  log.verbose(`Generating ${bundleDefinition.name}...`);
139
139
  return moduleBundler({
140
140
  resources,
@@ -2,6 +2,7 @@ const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateFle
2
2
  const flexChangesBundler = require("../../processors/bundlers/flexChangesBundler");
3
3
  const semver = require("semver");
4
4
 
5
+ /* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
5
6
  /**
6
7
  * Task to create changesBundle.json file containing all changes stored in the /changes folder for easier consumption
7
8
  * at runtime.
@@ -16,10 +17,13 @@ const semver = require("semver");
16
17
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
17
18
  * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
18
19
  * @param {object} [parameters.options] Options
19
- * @param {string} [parameters.options.namespace] Application Namespace
20
+ * @param {string} [parameters.options.projectNamespace] Project Namespace
20
21
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
21
22
  */
22
- module.exports = async function({workspace, taskUtil, options: {namespace}}) {
23
+ module.exports = async function({workspace, taskUtil, options = {}}) {
24
+ // Backward compatibility: "namespace" option got renamed to "projectNamespace"
25
+ const namespace = options.projectNamespace || options.namespace;
26
+
23
27
  // Use the given namespace if available, otherwise use no namespace
24
28
  // (e.g. in case no manifest.json is present)
25
29
  let pathPrefix = "";
@@ -1,6 +1,5 @@
1
1
  const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateLibraryPreload");
2
2
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
3
- const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
4
3
  const {negateFilters} = require("../../lbt/resources/ResourceFilterList");
5
4
  const createModuleNameMapping = require("./utils/createModuleNameMapping");
6
5
 
@@ -8,7 +7,7 @@ function getDefaultLibraryPreloadFilters(namespace, excludes) {
8
7
  const filters = [
9
8
  `${namespace}/`,
10
9
  `${namespace}/**/manifest.json`,
11
- `!${namespace}/*-preload.js`, // exclude all bundles
10
+ `!${namespace}/**/*-preload.js`, // exclude all bundles
12
11
  `!${namespace}/designtime/`,
13
12
  `!${namespace}/**/*.designtime.js`,
14
13
  `!${namespace}/**/*.support.js`
@@ -143,48 +142,6 @@ function getSupportFilesBundleDefinition(namespace) {
143
142
  };
144
143
  }
145
144
 
146
- function createLibraryBundles(libraryNamespace, resources, excludes) {
147
- return Promise.all([
148
- moduleBundler({
149
- options: {
150
- bundleDefinition: getBundleDefinition(libraryNamespace, excludes),
151
- bundleOptions: {
152
- optimize: true,
153
- usePredefineCalls: true,
154
- ignoreMissingModules: true
155
- }
156
- },
157
- resources
158
- }),
159
- moduleBundler({
160
- options: {
161
- bundleDefinition: getDesigntimeBundleDefinition(libraryNamespace),
162
- bundleOptions: {
163
- optimize: true,
164
- usePredefineCalls: true,
165
- ignoreMissingModules: true,
166
- skipIfEmpty: true
167
- }
168
- },
169
- resources
170
- }),
171
- moduleBundler({
172
- options: {
173
- bundleDefinition: getSupportFilesBundleDefinition(libraryNamespace),
174
- bundleOptions: {
175
- optimize: false,
176
- usePredefineCalls: true,
177
- ignoreMissingModules: true,
178
- skipIfEmpty: true
179
- }
180
- // Note: Although the bundle uses optimize=false, there is
181
- // no moduleNameMapping needed, as support files are excluded from minification.
182
- },
183
- resources
184
- })
185
- ]);
186
- }
187
-
188
145
  function getModuleBundlerOptions(config) {
189
146
  const moduleBundlerOptions = {};
190
147
 
@@ -266,32 +223,36 @@ function getSapUiCoreBunDef(name, filters, preload) {
266
223
  * @alias module:@ui5/builder.tasks.generateLibraryPreload
267
224
  * @param {object} parameters Parameters
268
225
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
269
- * @param {module:@ui5/fs.AbstractReader} parameters.dependencies Reader or Collection to read dependency files
270
- * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
226
+ * @param {module:@ui5/builder.tasks.TaskUtil} [parameters.taskUtil] TaskUtil
227
+ * @param {object} parameters.options Options
228
+ * @param {string} parameters.options.projectName Project name
229
+ * @param {string[]} [parameters.options.skipBundles] Names of bundles that should not be created
271
230
  * @param {string[]} [parameters.options.excludes=[]] List of modules declared as glob patterns (resource name patterns)
272
231
  * that should be excluded from the library-preload.js bundle.
273
232
  * A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk,
274
233
  * denote an arbitrary number of characters or folder names.
275
234
  * Re-includes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later
276
235
  * inclusion overrides an earlier exclusion, and vice versa.
277
- * @param {object} parameters.options Options
278
- * @param {string} parameters.options.projectName Project name
279
236
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
280
237
  */
281
- module.exports = function({workspace, dependencies, taskUtil, options: {projectName, excludes = []}}) {
282
- let combo = new ReaderCollectionPrioritized({
283
- name: `libraryBundler - prioritize workspace over dependencies: ${projectName}`,
284
- readers: [workspace, dependencies]
285
- });
286
-
238
+ module.exports = function({workspace, taskUtil, options: {skipBundles = [], excludes = [], projectName}}) {
239
+ let nonDbgWorkspace = workspace;
287
240
  if (taskUtil) {
288
- combo = combo.filter(function(resource) {
241
+ nonDbgWorkspace = workspace.filter(function(resource) {
289
242
  // Remove any debug variants
290
243
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant);
291
244
  });
292
245
  }
293
246
 
294
- return combo.byGlob("/**/*.{js,json,xml,html,properties,library,js.map}").then(async (resources) => {
247
+ const execModuleBundlerIfNeeded = ({options, resources}) => {
248
+ if (skipBundles.includes(options.bundleDefinition.name)) {
249
+ log.verbose(`Skipping generation of bundle ${options.bundleDefinition.name}`);
250
+ return null;
251
+ }
252
+ return moduleBundler({options, resources});
253
+ };
254
+
255
+ return nonDbgWorkspace.byGlob("/**/*.{js,json,xml,html,properties,library,js.map}").then(async (resources) => {
295
256
  // Find all libraries and create a library-preload.js bundle
296
257
 
297
258
  let p = Promise.resolve();
@@ -299,14 +260,12 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
299
260
  // Create core bundles for older versions (<1.97.0) which don't define bundle configuration in the ui5.yaml
300
261
  // See: https://github.com/SAP/openui5/commit/ff127fd2d009162ea43ad312dec99d759ebc23a0
301
262
  if (projectName === "sap.ui.core") {
302
- const coreProject = resources[0]._project;
303
- const coreSpecVersion = coreProject && coreProject.specVersion;
304
263
  // Instead of checking the sap.ui.core library version, the specVersion is checked against all versions
305
264
  // that have been defined for sap.ui.core before the bundle configuration has been introduced.
306
265
  // This is mainly to have an easier check without version parsing or using semver.
307
266
  // If no project/specVersion is available, the bundles should also be created to not break potential
308
267
  // existing use cases without a properly formed/formatted project tree.
309
- if (!coreSpecVersion || ["0.1", "1.1", "2.0"].includes(coreSpecVersion)) {
268
+ if (!taskUtil || ["0.1", "1.1", "2.0"].includes(taskUtil.getProject().getSpecVersion())) {
310
269
  const isEvo = resources.find((resource) => {
311
270
  return resource.getPath() === "/resources/ui5loader.js";
312
271
  });
@@ -314,10 +273,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
314
273
  let unoptimizedModuleNameMapping;
315
274
  let unoptimizedResources = resources;
316
275
  if (taskUtil) {
317
- unoptimizedResources = await new ReaderCollectionPrioritized({
318
- name: `libraryBundler - prioritize workspace over dependencies: ${projectName}`,
319
- readers: [workspace, dependencies]
320
- }).filter(function(resource) {
276
+ unoptimizedResources = await workspace.filter(function(resource) {
321
277
  // Remove any non-debug variants
322
278
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
323
279
  }).byGlob("/**/*.{js,json,xml,html,properties,library,js.map}");
@@ -335,24 +291,24 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
335
291
  filters = ["jquery.sap.global.js"];
336
292
  }
337
293
  p = Promise.all([
338
- moduleBundler({
294
+ execModuleBundlerIfNeeded({
339
295
  options: getModuleBundlerOptions({name: "sap-ui-core.js", filters, preload: true}),
340
296
  resources
341
297
  }),
342
- moduleBundler({
298
+ execModuleBundlerIfNeeded({
343
299
  options: getModuleBundlerOptions({
344
300
  name: "sap-ui-core-dbg.js", filters, preload: false,
345
301
  moduleNameMapping: unoptimizedModuleNameMapping
346
302
  }),
347
303
  resources: unoptimizedResources
348
304
  }),
349
- moduleBundler({
305
+ execModuleBundlerIfNeeded({
350
306
  options: getModuleBundlerOptions({
351
307
  name: "sap-ui-core-nojQuery.js", filters, preload: true, provided: true
352
308
  }),
353
309
  resources
354
310
  }),
355
- moduleBundler({
311
+ execModuleBundlerIfNeeded({
356
312
  options: getModuleBundlerOptions({
357
313
  name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true,
358
314
  moduleNameMapping: unoptimizedModuleNameMapping
@@ -360,7 +316,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
360
316
  resources: unoptimizedResources
361
317
  }),
362
318
  ]).then((results) => {
363
- const bundles = Array.prototype.concat.apply([], results);
319
+ const bundles = Array.prototype.concat.apply([], results).filter(Boolean);
364
320
  return Promise.all(bundles.map(({bundle, sourceMap}) => {
365
321
  if (taskUtil) {
366
322
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
@@ -387,7 +343,8 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
387
343
  } else {
388
344
  // Fallback to "library.js" as library indicator
389
345
  log.verbose(
390
- `Could not find a ".library" file for project ${projectName}, falling back to "library.js".`);
346
+ `Could not find a ".library" file for project ${projectName}, ` +
347
+ `falling back to "library.js".`);
391
348
  return workspace.byGlob("/resources/**/library.js");
392
349
  }
393
350
  }).then((libraryIndicatorResources) => {
@@ -399,7 +356,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
399
356
  return;
400
357
  }
401
358
 
402
- return Promise.all(libraryIndicatorResources.map((libraryIndicatorResource) => {
359
+ return Promise.all(libraryIndicatorResources.map(async (libraryIndicatorResource) => {
403
360
  // Determine library namespace from library indicator file path
404
361
  // ending with either ".library" or "library.js" (see fallback logic above)
405
362
  // e.g. /resources/sap/foo/.library => sap/foo
@@ -409,28 +366,64 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
409
366
  const libraryNamespaceMatch = libraryIndicatorPath.match(libraryNamespacePattern);
410
367
  if (libraryNamespaceMatch && libraryNamespaceMatch[1]) {
411
368
  const libraryNamespace = libraryNamespaceMatch[1];
412
- return createLibraryBundles(libraryNamespace, resources, excludes)
413
- .then((results) => {
414
- const bundles = Array.prototype.concat.apply([], results);
415
- return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
416
- if (bundle) {
417
- if (taskUtil) {
418
- taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
419
- if (sourceMap) {
420
- // Clear tag that might have been set by the minify task, in cases where
421
- // the bundle name is identical to a source file
422
- taskUtil.clearTag(sourceMap,
423
- taskUtil.STANDARD_TAGS.OmitFromBuildResult);
424
- }
425
- }
426
- const writes = [workspace.write(bundle)];
427
- if (sourceMap) {
428
- writes.push(workspace.write(sourceMap));
429
- }
430
- return Promise.all(writes);
369
+ const results = await Promise.all([
370
+ execModuleBundlerIfNeeded({
371
+ options: {
372
+ bundleDefinition: getBundleDefinition(libraryNamespace, excludes),
373
+ bundleOptions: {
374
+ optimize: true,
375
+ usePredefineCalls: true,
376
+ ignoreMissingModules: true
431
377
  }
432
- }));
433
- });
378
+ },
379
+ resources
380
+ }),
381
+ execModuleBundlerIfNeeded({
382
+ options: {
383
+ bundleDefinition: getDesigntimeBundleDefinition(libraryNamespace),
384
+ bundleOptions: {
385
+ optimize: true,
386
+ usePredefineCalls: true,
387
+ ignoreMissingModules: true,
388
+ skipIfEmpty: true
389
+ }
390
+ },
391
+ resources
392
+ }),
393
+ execModuleBundlerIfNeeded({
394
+ options: {
395
+ bundleDefinition: getSupportFilesBundleDefinition(libraryNamespace),
396
+ bundleOptions: {
397
+ optimize: false,
398
+ usePredefineCalls: true,
399
+ ignoreMissingModules: true,
400
+ skipIfEmpty: true
401
+ }
402
+ // Note: Although the bundle uses optimize=false, there is
403
+ // no moduleNameMapping needed, as support files are excluded from minification.
404
+ },
405
+ resources
406
+ })
407
+ ]);
408
+ const bundles = Array.prototype.concat.apply([], results).filter(Boolean);
409
+ return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
410
+ if (bundle) {
411
+ if (taskUtil) {
412
+ taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
413
+ if (sourceMap) {
414
+ // Clear tag that might have been set by the minify task, in cases where
415
+ // the bundle name is identical to a source file
416
+ taskUtil.clearTag(sourceMap,
417
+ taskUtil.STANDARD_TAGS.OmitFromBuildResult);
418
+ }
419
+ }
420
+ const writes = [workspace.write(bundle)];
421
+ if (sourceMap) {
422
+ writes.push(workspace.write(sourceMap));
423
+ }
424
+ return Promise.all(writes);
425
+ }
426
+ }));
434
427
  } else {
435
428
  log.verbose(
436
429
  `Could not determine library namespace from file "${libraryIndicatorPath}" ` +
@@ -4,14 +4,7 @@ const DESCRIPTOR = "manifest.json";
4
4
  const PROPERTIES_EXT = ".properties";
5
5
  const BUNDLE_NAME = "manifest-bundle.zip";
6
6
 
7
- /**
8
- *
9
- * @public
10
- * @typedef {object} ManifestBundlerOptions
11
- * @property {string} projectName Project Name
12
- * @property {string} namespace Namespace
13
- */
14
-
7
+ /* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
15
8
  /**
16
9
  * Task for manifestBundler.
17
10
  *
@@ -19,11 +12,16 @@ const BUNDLE_NAME = "manifest-bundle.zip";
19
12
  * @alias module:@ui5/builder.tasks.generateManifestBundle
20
13
  * @param {object} parameters Parameters
21
14
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
22
- * @param {ManifestBundlerOptions} parameters.options Options
15
+ * @param {object} parameters.options Options
16
+ * @param {string} parameters.options.projectName Project name
17
+ * @param {string} parameters.options.projectNamespace Project namespace
23
18
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
24
19
  */
25
20
  module.exports = async function({workspace, options = {}}) {
26
- const {projectName, namespace} = options;
21
+ const {projectName} = options;
22
+ // Backward compatibility: "namespace" option got renamed to "projectNamespace"
23
+ const namespace = options.projectNamespace || options.namespace;
24
+
27
25
  if (!projectName || !namespace) {
28
26
  throw new Error("[generateManifestBundle]: One or more mandatory options not provided");
29
27
  }
@@ -58,6 +58,7 @@ function getBundleDefinition(config) {
58
58
  return bundleDefinition;
59
59
  }
60
60
 
61
+ /* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
61
62
  /**
62
63
  * Task for bundling standalone applications.
63
64
  *
@@ -69,10 +70,14 @@ function getBundleDefinition(config) {
69
70
  * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
70
71
  * @param {object} parameters.options Options
71
72
  * @param {string} parameters.options.projectName Project name
72
- * @param {string} [parameters.options.namespace] Project namespace
73
+ * @param {string} [parameters.options.projectNamespace] Project namespace
73
74
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
74
75
  */
75
- module.exports = async function({workspace, dependencies, taskUtil, options: {projectName, namespace}}) {
76
+ module.exports = async function({workspace, dependencies, taskUtil, options}) {
77
+ const {projectName} = options;
78
+ // Backward compatibility: "namespace" option got renamed to "projectNamespace"
79
+ const namespace = options.projectNamespace || options.namespace;
80
+
76
81
  if (!namespace) {
77
82
  log.warn(`Namespace of project ${projectName} is not known. Self contained bundling is currently ` +
78
83
  `unable to generate complete bundles for such projects.`);
@@ -17,8 +17,9 @@ const ModuleName = require("../../../lbt/utils/ModuleName");
17
17
  module.exports = function({resources, taskUtil}) {
18
18
  const moduleNameMapping = {};
19
19
  for (let i = resources.length - 1; i >= 0; i--) {
20
- const resourcePath = resources[i].getPath();
21
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
20
+ const resource = resources[i];
21
+ if (taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
22
+ const resourcePath = resource.getPath();
22
23
  const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
23
24
  if (!nonDbgPath) {
24
25
  throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
@@ -28,6 +28,7 @@ function getSigner(type) {
28
28
  }
29
29
  }
30
30
 
31
+ /* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
31
32
  /**
32
33
  * Task to generate the application cachebuster info file.
33
34
  *
@@ -35,13 +36,16 @@ function getSigner(type) {
35
36
  * @alias module:@ui5/builder.tasks.generateCachebusterInfo
36
37
  * @param {object} parameters Parameters
37
38
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
38
- * @param {module:@ui5/fs.AbstractReader} parameters.dependencies Reader or Collection to read dependency files
39
39
  * @param {object} parameters.options Options
40
- * @param {string} parameters.options.namespace Namespace of the application
40
+ * @param {string} parameters.options.projectNamespace Namespace of the application
41
41
  * @param {string} [parameters.options.signatureType='time'] Type of signature to be used ('time' or 'hash')
42
42
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
43
43
  */
44
- module.exports = function({workspace, dependencies, options: {namespace, signatureType}}) {
44
+ module.exports = function({workspace, options}) {
45
+ const {signatureType} = options;
46
+ // Backward compatibility: "namespace" option got renamed to "projectNamespace"
47
+ const namespace = options.projectNamespace || options.namespace;
48
+
45
49
  const basePath = `/resources/${namespace}/`;
46
50
  return workspace.byGlob(`/resources/${namespace}/**/*`)
47
51
  .then(async (resources) => {