@ui5/builder 3.0.0-alpha.1 → 3.0.0-alpha.10

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 (60) hide show
  1. package/CHANGELOG.md +850 -0
  2. package/index.js +0 -43
  3. package/lib/lbt/analyzer/JSModuleAnalyzer.js +27 -8
  4. package/lib/lbt/analyzer/XMLTemplateAnalyzer.js +2 -1
  5. package/lib/lbt/bundle/Builder.js +364 -137
  6. package/lib/lbt/bundle/BundleWriter.js +17 -0
  7. package/lib/lbt/bundle/Resolver.js +2 -2
  8. package/lib/lbt/resources/LocatorResource.js +7 -7
  9. package/lib/lbt/resources/LocatorResourcePool.js +8 -4
  10. package/lib/lbt/resources/ResourceCollector.js +22 -15
  11. package/lib/lbt/resources/ResourceInfoList.js +0 -1
  12. package/lib/lbt/resources/ResourcePool.js +7 -6
  13. package/lib/lbt/utils/escapePropertiesFile.js +3 -6
  14. package/lib/lbt/utils/parseUtils.js +1 -1
  15. package/lib/processors/bundlers/moduleBundler.js +31 -10
  16. package/lib/processors/jsdoc/lib/createIndexFiles.js +1 -1
  17. package/lib/processors/jsdoc/lib/transformApiJson.js +20 -20
  18. package/lib/processors/jsdoc/lib/ui5/plugin.js +111 -6
  19. package/lib/processors/jsdoc/lib/ui5/template/publish.js +112 -91
  20. package/lib/processors/jsdoc/lib/ui5/template/utils/versionUtil.js +1 -1
  21. package/lib/processors/manifestCreator.js +8 -45
  22. package/lib/processors/minifier.js +11 -5
  23. package/lib/tasks/buildThemes.js +1 -1
  24. package/lib/tasks/bundlers/generateBundle.js +70 -30
  25. package/lib/tasks/bundlers/generateComponentPreload.js +26 -19
  26. package/lib/tasks/bundlers/generateFlexChangesBundle.js +10 -5
  27. package/lib/tasks/bundlers/generateLibraryPreload.js +113 -94
  28. package/lib/tasks/bundlers/generateManifestBundle.js +8 -10
  29. package/lib/tasks/bundlers/generateStandaloneAppBundle.js +42 -10
  30. package/lib/tasks/bundlers/utils/createModuleNameMapping.js +31 -0
  31. package/lib/tasks/generateCachebusterInfo.js +7 -3
  32. package/lib/tasks/generateLibraryManifest.js +6 -8
  33. package/lib/tasks/generateResourcesJson.js +3 -3
  34. package/lib/tasks/generateThemeDesignerResources.js +118 -2
  35. package/lib/tasks/generateVersionInfo.js +5 -5
  36. package/lib/tasks/jsdoc/generateJsdoc.js +1 -1
  37. package/lib/tasks/minify.js +14 -4
  38. package/lib/tasks/taskRepository.js +1 -13
  39. package/lib/tasks/transformBootstrapHtml.js +6 -1
  40. package/package.json +11 -10
  41. package/lib/builder/BuildContext.js +0 -56
  42. package/lib/builder/ProjectBuildContext.js +0 -57
  43. package/lib/builder/builder.js +0 -419
  44. package/lib/tasks/TaskUtil.js +0 -160
  45. package/lib/types/AbstractBuilder.js +0 -270
  46. package/lib/types/AbstractFormatter.js +0 -66
  47. package/lib/types/AbstractUi5Formatter.js +0 -95
  48. package/lib/types/application/ApplicationBuilder.js +0 -211
  49. package/lib/types/application/ApplicationFormatter.js +0 -227
  50. package/lib/types/application/applicationType.js +0 -15
  51. package/lib/types/library/LibraryBuilder.js +0 -231
  52. package/lib/types/library/LibraryFormatter.js +0 -519
  53. package/lib/types/library/libraryType.js +0 -15
  54. package/lib/types/module/ModuleBuilder.js +0 -7
  55. package/lib/types/module/ModuleFormatter.js +0 -54
  56. package/lib/types/module/moduleType.js +0 -15
  57. package/lib/types/themeLibrary/ThemeLibraryBuilder.js +0 -63
  58. package/lib/types/themeLibrary/ThemeLibraryFormatter.js +0 -90
  59. package/lib/types/themeLibrary/themeLibraryType.js +0 -15
  60. package/lib/types/typeRepository.js +0 -46
@@ -1,5 +1,5 @@
1
1
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
2
- const ModuleName = require("../../lbt/utils/ModuleName");
2
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
3
3
  const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
4
4
 
5
5
  /**
@@ -10,7 +10,7 @@ const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritiz
10
10
  * @param {object} parameters Parameters
11
11
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
12
12
  * @param {module:@ui5/fs.ReaderCollection} parameters.dependencies Collection to read dependency files
13
- * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
13
+ * @param {module:@ui5/project.build.helpers.TaskUtil|object} [parameters.taskUtil] TaskUtil
14
14
  * @param {object} parameters.options Options
15
15
  * @param {string} parameters.options.projectName Project name
16
16
  * @param {ModuleBundleDefinition} parameters.options.bundleDefinition Module bundle definition
@@ -21,12 +21,57 @@ module.exports = function({
21
21
  workspace, dependencies, taskUtil, options: {projectName, bundleDefinition, bundleOptions}
22
22
  }) {
23
23
  let combo = new ReaderCollectionPrioritized({
24
- name: `libraryBundler - prioritize workspace over dependencies: ${projectName}`,
24
+ name: `generateBundle - prioritize workspace over dependencies: ${projectName}`,
25
25
  readers: [workspace, dependencies]
26
26
  });
27
27
 
28
+ const optimize = !bundleOptions || bundleOptions.optimize !== false;
28
29
  if (taskUtil) {
29
- const optimize = !bundleOptions || bundleOptions.optimize !== false;
30
+ /* Scenarios
31
+ 1. Optimize bundle with minification already done
32
+ Workspace:
33
+ * /resources/my/lib/Control.js [ui5:HasDebugVariant]
34
+ * /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
35
+ * /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
36
+
37
+ Bundler input:
38
+ * /resources/my/lib/Control.js
39
+ * /resources/my/lib/Control.js.map
40
+
41
+ => Filter out debug resources
42
+
43
+ 2. Optimize bundle with no minification
44
+ * /resources/my/lib/Control.js
45
+
46
+ => No action necessary
47
+
48
+ 3. Debug-bundle with minification already done
49
+ Workspace:
50
+ * /resources/my/lib/Control.js [ui5:HasDebugVariant]
51
+ * /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
52
+ * /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
53
+
54
+ Bundler input:
55
+ * /resources/my/lib/Control-dbg.js
56
+ * moduleNameMapping: [{"/resources/my/lib/Control-dbg.js": "my/lib/Control.js"}]
57
+
58
+ => Filter out minified-resources (tagged as "HasDebugVariant", incl. source maps) and rename debug-files
59
+
60
+ 4. Debug-bundle with no minification
61
+ * /resources/my/lib/Control.js
62
+
63
+ => No action necessary
64
+
65
+ 5. Bundle with external input (optimize or not), e.g. TS-project
66
+ Workspace:
67
+ * /resources/my/lib/Control.ts
68
+ * /resources/my/lib/Control.js
69
+ * /resources/my/lib/Control.js.map
70
+
71
+ Bundler input:
72
+ * /resources/my/lib/Control.js
73
+ * /resources/my/lib/Control.js.map
74
+ */
30
75
 
31
76
  // Omit -dbg files for optimize bundles and vice versa
32
77
  const filterTag = optimize ?
@@ -34,37 +79,32 @@ module.exports = function({
34
79
  combo = combo.filter(function(resource) {
35
80
  return !taskUtil.getTag(resource, filterTag);
36
81
  });
37
-
38
- if (!optimize) {
39
- // For "unoptimized" bundles, the non-debug files have already been filtered out
40
- // Now rename the debug variants to the same name so that they appear like the original
41
- // resource to the bundler
42
- combo = combo.transformer(async function(resourcePath, getResource) {
43
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
44
- const resource = await getResource();
45
- const nonDbgPath = ModuleName.getNonDebugName(resource.getPath());
46
- if (!nonDbgPath) {
47
- throw new Error(`Failed to resolve non-debug name for ${resource.getPath()}`);
48
- }
49
- resource.setPath(nonDbgPath);
50
- }
51
- });
52
- }
53
82
  }
54
83
 
55
- return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library}").then((resources) => {
56
- return moduleBundler({
57
- options: {
58
- bundleDefinition,
59
- bundleOptions
60
- },
61
- resources
62
- }).then((bundles) => {
63
- return Promise.all(bundles.map((bundle) => {
84
+ return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
85
+ const options = {bundleDefinition, bundleOptions};
86
+ if (!optimize && taskUtil) {
87
+ options.moduleNameMapping = createModuleNameMapping({resources, taskUtil});
88
+ }
89
+ return moduleBundler({options, resources}).then((bundles) => {
90
+ return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
91
+ if (!bundle) {
92
+ // Skip empty bundles
93
+ return;
94
+ }
64
95
  if (taskUtil) {
65
96
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
97
+ if (sourceMap) {
98
+ // Clear tag that might have been set by the minify task, in cases where
99
+ // the bundle name is identical to a source file
100
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
101
+ }
102
+ }
103
+ const writes = [workspace.write(bundle)];
104
+ if (sourceMap) {
105
+ writes.push(workspace.write(sourceMap));
66
106
  }
67
- return workspace.write(bundle);
107
+ return Promise.all(writes);
68
108
  }));
69
109
  });
70
110
  });
@@ -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,8 +10,7 @@ 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
- * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
13
+ * @param {module:@ui5/project.build.helpers.TaskUtil|object} [parameters.taskUtil] TaskUtil
16
14
  * @param {object} parameters.options Options
17
15
  * @param {string} parameters.options.projectName Project name
18
16
  * @param {string[]} [parameters.options.excludes=[]] List of modules declared as glob patterns (resource name patterns)
@@ -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}")
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,
@@ -148,12 +148,19 @@ module.exports = function({
148
148
  });
149
149
  }));
150
150
  })
151
- .then((processedResources) => {
152
- return Promise.all(processedResources.map((resource) => {
151
+ .then((results) => {
152
+ const bundles = Array.prototype.concat.apply([], results);
153
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
153
154
  if (taskUtil) {
154
- taskUtil.setTag(resource[0], taskUtil.STANDARD_TAGS.IsBundle);
155
+ taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
156
+ // Clear tag that might have been set by the minify task, in cases where
157
+ // the bundle name is identical to a source file
158
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
155
159
  }
156
- return workspace.write(resource[0]);
160
+ return Promise.all([
161
+ workspace.write(bundle),
162
+ workspace.write(sourceMap)
163
+ ]);
157
164
  }));
158
165
  });
159
166
  };
@@ -1,6 +1,8 @@
1
1
  const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateFlexChangesBundle");
2
2
  const flexChangesBundler = require("../../processors/bundlers/flexChangesBundler");
3
+ const semver = require("semver");
3
4
 
5
+ /* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
4
6
  /**
5
7
  * Task to create changesBundle.json file containing all changes stored in the /changes folder for easier consumption
6
8
  * at runtime.
@@ -13,12 +15,15 @@ const flexChangesBundler = require("../../processors/bundlers/flexChangesBundler
13
15
  * @alias module:@ui5/builder.tasks.generateFlexChangesBundle
14
16
  * @param {object} parameters Parameters
15
17
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
16
- * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
18
+ * @param {module:@ui5/project.build.helpers.TaskUtil|object} [parameters.taskUtil] TaskUtil
17
19
  * @param {object} [parameters.options] Options
18
- * @param {string} [parameters.options.namespace] Application Namespace
20
+ * @param {string} [parameters.options.projectNamespace] Project Namespace
19
21
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
20
22
  */
21
- 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
+
22
27
  // Use the given namespace if available, otherwise use no namespace
23
28
  // (e.g. in case no manifest.json is present)
24
29
  let pathPrefix = "";
@@ -68,9 +73,9 @@ module.exports = async function({workspace, taskUtil, options: {namespace}}) {
68
73
  const allResources = await workspace.byGlob(
69
74
  `${pathPrefix}/changes/*.{change,variant,ctrl_variant,ctrl_variant_change,ctrl_variant_management_change}`);
70
75
  if (allResources.length > 0) {
71
- const version = await readManifestMinUI5Version();
76
+ const version = semver.coerce(await readManifestMinUI5Version());
72
77
  let hasFlexBundleVersion = false;
73
- if (parseFloat(version) >= 1.73) {
78
+ if (semver.compare(version, "1.73.0") >= 0) {
74
79
  hasFlexBundleVersion = true;
75
80
  }
76
81
  const processedResources = await flexChangesBundler({
@@ -1,14 +1,13 @@
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
- const ModuleName = require("../../lbt/utils/ModuleName");
4
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
6
5
 
7
6
  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,46 +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
- },
181
- resources
182
- })
183
- ]);
184
- }
185
-
186
145
  function getModuleBundlerOptions(config) {
187
146
  const moduleBundlerOptions = {};
188
147
 
@@ -212,6 +171,10 @@ function getModuleBundlerOptions(config) {
212
171
  moduleBundlerOptions.bundleDefinition.sections.unshift(providedSection);
213
172
  }
214
173
 
174
+ if (config.moduleNameMapping) {
175
+ moduleBundlerOptions.moduleNameMapping = config.moduleNameMapping;
176
+ }
177
+
215
178
  return moduleBundlerOptions;
216
179
  }
217
180
 
@@ -260,32 +223,36 @@ function getSapUiCoreBunDef(name, filters, preload) {
260
223
  * @alias module:@ui5/builder.tasks.generateLibraryPreload
261
224
  * @param {object} parameters Parameters
262
225
  * @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
263
- * @param {module:@ui5/fs.AbstractReader} parameters.dependencies Reader or Collection to read dependency files
264
- * @param {module:@ui5/builder.tasks.TaskUtil|object} [parameters.taskUtil] TaskUtil
226
+ * @param {module:@ui5/project.build.helpers.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
265
230
  * @param {string[]} [parameters.options.excludes=[]] List of modules declared as glob patterns (resource name patterns)
266
231
  * that should be excluded from the library-preload.js bundle.
267
232
  * A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk,
268
233
  * denote an arbitrary number of characters or folder names.
269
234
  * Re-includes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later
270
235
  * inclusion overrides an earlier exclusion, and vice versa.
271
- * @param {object} parameters.options Options
272
- * @param {string} parameters.options.projectName Project name
273
236
  * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
274
237
  */
275
- module.exports = function({workspace, dependencies, taskUtil, options: {projectName, excludes = []}}) {
276
- let combo = new ReaderCollectionPrioritized({
277
- name: `libraryBundler - prioritize workspace over dependencies: ${projectName}`,
278
- readers: [workspace, dependencies]
279
- });
280
-
238
+ module.exports = function({workspace, taskUtil, options: {skipBundles = [], excludes = [], projectName}}) {
239
+ let nonDbgWorkspace = workspace;
281
240
  if (taskUtil) {
282
- combo = combo.filter(function(resource) {
241
+ nonDbgWorkspace = workspace.filter(function(resource) {
283
242
  // Remove any debug variants
284
243
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant);
285
244
  });
286
245
  }
287
246
 
288
- return combo.byGlob("/**/*.{js,json,xml,html,properties,library}").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) => {
289
256
  // Find all libraries and create a library-preload.js bundle
290
257
 
291
258
  let p = Promise.resolve();
@@ -293,36 +260,28 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
293
260
  // Create core bundles for older versions (<1.97.0) which don't define bundle configuration in the ui5.yaml
294
261
  // See: https://github.com/SAP/openui5/commit/ff127fd2d009162ea43ad312dec99d759ebc23a0
295
262
  if (projectName === "sap.ui.core") {
296
- const coreProject = resources[0]._project;
297
- const coreSpecVersion = coreProject && coreProject.specVersion;
298
263
  // Instead of checking the sap.ui.core library version, the specVersion is checked against all versions
299
264
  // that have been defined for sap.ui.core before the bundle configuration has been introduced.
300
265
  // This is mainly to have an easier check without version parsing or using semver.
301
266
  // If no project/specVersion is available, the bundles should also be created to not break potential
302
267
  // existing use cases without a properly formed/formatted project tree.
303
- if (!coreSpecVersion || ["0.1", "1.1", "2.0"].includes(coreSpecVersion)) {
268
+ if (!taskUtil || ["0.1", "1.1", "2.0"].includes(taskUtil.getProject().getSpecVersion())) {
304
269
  const isEvo = resources.find((resource) => {
305
270
  return resource.getPath() === "/resources/ui5loader.js";
306
271
  });
307
272
 
273
+ let unoptimizedModuleNameMapping;
308
274
  let unoptimizedResources = resources;
309
275
  if (taskUtil) {
310
- unoptimizedResources = await new ReaderCollectionPrioritized({
311
- name: `libraryBundler - prioritize workspace over dependencies: ${projectName}`,
312
- readers: [workspace, dependencies]
313
- }).filter(function(resource) {
276
+ unoptimizedResources = await workspace.filter(function(resource) {
314
277
  // Remove any non-debug variants
315
278
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
316
- }).transformer(async function(resourcePath, getResource) {
317
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
318
- const resource = await getResource();
319
- const nonDbgPath = ModuleName.getNonDebugName(resource.getPath());
320
- if (!nonDbgPath) {
321
- throw new Error(`Failed to resolve non-debug name for ${resource.getPath()}`);
322
- }
323
- resource.setPath(nonDbgPath);
324
- }
325
- }).byGlob("/**/*.{js,json,xml,html,properties,library}");
279
+ }).byGlob("/**/*.{js,json,xml,html,properties,library,js.map}");
280
+
281
+ unoptimizedModuleNameMapping = createModuleNameMapping({
282
+ resources: unoptimizedResources,
283
+ taskUtil
284
+ });
326
285
  }
327
286
 
328
287
  let filters;
@@ -332,33 +291,46 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
332
291
  filters = ["jquery.sap.global.js"];
333
292
  }
334
293
  p = Promise.all([
335
- moduleBundler({
294
+ execModuleBundlerIfNeeded({
336
295
  options: getModuleBundlerOptions({name: "sap-ui-core.js", filters, preload: true}),
337
296
  resources
338
297
  }),
339
- moduleBundler({
340
- options: getModuleBundlerOptions({name: "sap-ui-core-dbg.js", filters, preload: false}),
298
+ execModuleBundlerIfNeeded({
299
+ options: getModuleBundlerOptions({
300
+ name: "sap-ui-core-dbg.js", filters, preload: false,
301
+ moduleNameMapping: unoptimizedModuleNameMapping
302
+ }),
341
303
  resources: unoptimizedResources
342
304
  }),
343
- moduleBundler({
305
+ execModuleBundlerIfNeeded({
344
306
  options: getModuleBundlerOptions({
345
307
  name: "sap-ui-core-nojQuery.js", filters, preload: true, provided: true
346
308
  }),
347
309
  resources
348
310
  }),
349
- moduleBundler({
311
+ execModuleBundlerIfNeeded({
350
312
  options: getModuleBundlerOptions({
351
- name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true
313
+ name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true,
314
+ moduleNameMapping: unoptimizedModuleNameMapping
352
315
  }),
353
316
  resources: unoptimizedResources
354
317
  }),
355
318
  ]).then((results) => {
356
- const bundles = Array.prototype.concat.apply([], results);
357
- return Promise.all(bundles.map((bundle) => {
319
+ const bundles = Array.prototype.concat.apply([], results).filter(Boolean);
320
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
358
321
  if (taskUtil) {
359
322
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
323
+ if (sourceMap) {
324
+ // Clear tag that might have been set by the minify task, in cases where
325
+ // the bundle name is identical to a source file
326
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
327
+ }
328
+ }
329
+ const writes = [workspace.write(bundle)];
330
+ if (sourceMap) {
331
+ writes.push(workspace.write(sourceMap));
360
332
  }
361
- return workspace.write(bundle);
333
+ return Promise.all(writes);
362
334
  }));
363
335
  });
364
336
  }
@@ -371,7 +343,8 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
371
343
  } else {
372
344
  // Fallback to "library.js" as library indicator
373
345
  log.verbose(
374
- `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".`);
375
348
  return workspace.byGlob("/resources/**/library.js");
376
349
  }
377
350
  }).then((libraryIndicatorResources) => {
@@ -383,7 +356,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
383
356
  return;
384
357
  }
385
358
 
386
- return Promise.all(libraryIndicatorResources.map((libraryIndicatorResource) => {
359
+ return Promise.all(libraryIndicatorResources.map(async (libraryIndicatorResource) => {
387
360
  // Determine library namespace from library indicator file path
388
361
  // ending with either ".library" or "library.js" (see fallback logic above)
389
362
  // e.g. /resources/sap/foo/.library => sap/foo
@@ -393,18 +366,64 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
393
366
  const libraryNamespaceMatch = libraryIndicatorPath.match(libraryNamespacePattern);
394
367
  if (libraryNamespaceMatch && libraryNamespaceMatch[1]) {
395
368
  const libraryNamespace = libraryNamespaceMatch[1];
396
- return createLibraryBundles(libraryNamespace, resources, excludes)
397
- .then((results) => {
398
- const bundles = Array.prototype.concat.apply([], results);
399
- return Promise.all(bundles.map((bundle) => {
400
- if (bundle) {
401
- if (taskUtil) {
402
- taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
403
- }
404
- return workspace.write(bundle);
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
377
+ }
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
405
389
  }
406
- }));
407
- });
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
+ }));
408
427
  } else {
409
428
  log.verbose(
410
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
  }