import moduleBundler from "../../processors/bundlers/moduleBundler.js";
import {applyDefaultsToBundleDefinition} from "./utils/applyDefaultsToBundleDefinition.js";
import createModuleNameMapping from "./utils/createModuleNameMapping.js";
import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
/**
* @public
* @module @ui5/builder/tasks/bundlers/generateBundle
*/
/* eslint-disable max-len */
/**
* Generates a bundle based on the given bundle definition
*
* @public
* @function default
* @static
*
* @param {object} parameters Parameters
* @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
* @param {@ui5/fs/ReaderCollection} parameters.dependencies Collection to read dependency files
* @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
* @param {object} parameters.options Options
* @param {string} parameters.options.projectName Project name
* @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition} parameters.options.bundleDefinition Module
* bundle definition
* @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleOptions} [parameters.options.bundleOptions] Module
* bundle options
* @returns {Promise} Promise resolving with <code>undefined</code> once data has been written
*/
/* eslint-enable max-len */
export default async function({
workspace, dependencies, taskUtil, options: {projectName, bundleDefinition, bundleOptions}
}) {
let combo = new ReaderCollectionPrioritized({
name: `generateBundle - prioritize workspace over dependencies: ${projectName}`,
readers: [workspace, dependencies]
});
const optimize = !bundleOptions || bundleOptions.optimize !== false;
if (taskUtil) {
/* Scenarios
1. Optimize bundle with minification already done
Workspace:
* /resources/my/lib/Control.js [ui5:HasDebugVariant]
* /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
* /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
Bundler input:
* /resources/my/lib/Control.js
* /resources/my/lib/Control.js.map
=> Filter out debug resources
2. Optimize bundle with no minification
* /resources/my/lib/Control.js
=> No action necessary
3. Debug-bundle with minification already done
Workspace:
* /resources/my/lib/Control.js [ui5:HasDebugVariant]
* /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
* /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
Bundler input:
* /resources/my/lib/Control-dbg.js
* moduleNameMapping: [{"/resources/my/lib/Control-dbg.js": "my/lib/Control.js"}]
=> Filter out minified-resources (tagged as "HasDebugVariant", incl. source maps) and rename debug-files
4. Debug-bundle with no minification
* /resources/my/lib/Control.js
=> No action necessary
5. Bundle with external input (optimize or not), e.g. TS-project
Workspace:
* /resources/my/lib/Control.ts
* /resources/my/lib/Control.js
* /resources/my/lib/Control.js.map
Bundler input:
* /resources/my/lib/Control.js
* /resources/my/lib/Control.js.map
*/
// Omit -dbg files for optimize bundles and vice versa
const filterTag = optimize ?
taskUtil.STANDARD_TAGS.IsDebugVariant : taskUtil.STANDARD_TAGS.HasDebugVariant;
combo = taskUtil.resourceFactory.createFilterReader({
reader: combo,
callback: function(resource) {
return !taskUtil.getTag(resource, filterTag);
}
});
}
const coreVersion = taskUtil?.getProject("sap.ui.core")?.getVersion();
const allowStringBundling = taskUtil?.getProject().getSpecVersion().lt("4.0");
return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
const options = {
bundleDefinition: applyDefaultsToBundleDefinition(bundleDefinition, taskUtil),
bundleOptions,
allowStringBundling
};
if (!optimize && taskUtil) {
options.moduleNameMapping = createModuleNameMapping({resources, taskUtil});
}
if (coreVersion) {
options.targetUi5CoreVersion = coreVersion;
}
return moduleBundler({options, resources}).then((bundles) => {
return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
if (!bundle) {
// Skip empty bundles
return;
}
if (taskUtil) {
taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
if (sourceMap) {
// Clear tag that might have been set by the minify task, in cases where
// the bundle name is identical to a source file
taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
}
}
const writes = [workspace.write(bundle)];
if (sourceMap) {
writes.push(workspace.write(sourceMap));
}
return Promise.all(writes);
}));
});
});
}