/**
* @file exports/index.js
* @copyright @spmhome @_2025
* @author Scott Meesseman @spmeesseman
*//** */
const cache = require("./cache");
const entry = require("./entry");
const rules = require("./rules");
const stats = require("./stats");
const watch = require("./watch");
const output = require("./output");
const devtool = require("./devtool");
const plugins = require("./plugins");
const resolve = require("./resolve");
const externals = require("./externals");
const ignoreWarnings = require("./ignore");
const experiments = require("./experiments");
const optimization = require("./optimization");
const infrastructureLogging = require("./infrastructure");
const { printBuildProperties } = require("../utils/print");
const { existsSync, resolvePath } = require("@spmhome/cmn-utils");
const { isEmpty, asArray, isString } = require("@spmhome/type-utils");
const { SpmhMessageUtils, withColor } = require("@spmhome/log-utils");
// /**
// * @type {Record<WpwBuildOptionsExportKey, typeof WpwWebpackExport>}
// */
const webpackExportModules = {
experiments, cache, entry, externals, optimization, output, resolve, devtool, rules, watch,
ignoreWarnings, infrastructureLogging, stats, plugins
};
/**
* @param {WpwBuild} build
* @returns {WpwWebpackConfig}
*/
const webpackDefaultExports = (build) =>
{
const b = build, p = build.pkgJson;
// recordsDir = join(b.virtualEntry.dir, "records");
// if (!existsSync(recordsDir)) {
// createDirSync(recordsDir);
// }
/** @type {WpwWebpackConfig} */
const wpCfg = {
entry: {},
stats: {},
plugins: [],
resolve: {},
snapshot: {},
mode: b.mode,
watch: false,
externals: [],
experiments: {},
optimization: {},
target: b.target,
resolveLoader: {},
devtool: undefined,
ignoreWarnings: [],
module: { rules: [] },
infrastructureLogging: {},
context: b.getContextPath(),
profile: b.logger.level >= 4,
parallelism: 8 * b.buildCount,
// recordsPath: join(recordsDir, "index.json"),
// recordsInputPath: join(recordsDir, "input.json"),
// recordsOutputPath: join(recordsDir, "output.json"),
cache: { type: "filesystem", buildDependencies: {} },
output: { path: b.getDistPath({ rel: true }) }, // eslint-disable-next-line stylistic/max-len
name: `${p.scopedName.name} v${p.version} [build::${b.name}] [type::${b.type}] [mode::${b.mode}] [tgt::${asArray(b.target).join("|")}]`
};
return wpCfg;
};
/**
* @param {string} name
* @param {function(WpwBuild): WpwWebpackExport} createFn
* @param {WpwBuild} build
* @param {WpwWebpackConfig} wpc
* @returns {any}
*/
const exportConfig = (name, createFn, build, wpc) =>
{
const xTags = [ "exports", name ],
initializationMsg = `create '${name.toLowerCase()}' configuration [${build.type}][${asArray(build.target).join("|")}]`;
build.wpc = wpc;
if (!build.hasError)
{
const cStaticPad = build.logger.staticPad;
build.logger.start(initializationMsg, 1);
build.logger.staticPad += " ";
try {
createFn(build);
}
catch(e)
{ build.addMessage({
exception: e,
code: SpmhMessageUtils.Code.ERROR_EXPORT_FAILED,
message: `failed to ${initializationMsg}`
}, true);
}
finally {
build.logger.staticPad = cStaticPad;
}
if (!build.hasError) {
build.logger.success(initializationMsg, 1, " ", !build.hasError, xTags);
}
else {
build.logger.fail(initializationMsg, 1, " ", !build.hasError, [ "invalid", ...xTags ]);
}
}
else
{ build.logger.success(
initializationMsg, 1, " ", false, [ "skipped", ...xTags ], build.hasError
);
}
};
/**
* @param {WpwBuild} build
* @param {string} lPad
* @returns {WpwWebpackConfig}
* @throws {Error}
*/
const webpackExports = (build, lPad) =>
{
const l = build.logger.write(
`create webpack configuration for ${build.name}::${asArray(build.target).join("|")}`, 1, lPad
);
try
{ let isRebuild = build.isRebuild;
const wpc = webpackDefaultExports(build);
if (build.errors.length > 0)
{ l.write("unable to configure webpack exports:", undefined, "", l.icons.color.error);
build.errors.splice(0).forEach(e => { l.sep(undefined, l.icons.color.error); l.error(e); });
l.sep(undefined, l.icons.color.error);
throw new Error("failed to configure webpack exports [details in log output]");
}
if (!build.isRebuild && isString(wpc.output.filename, true) && isString(wpc.output.path, true))
{ let name = wpc.output.filename;
if (name === "[name].js") {
name = `${build.name}.js`;
}
if (name) {
isRebuild = !existsSync(resolvePath(wpc.output.path, name));
}
}
if (isRebuild) {
wpc.name = wpc.name.replace("build::", "rebuild::");
}
this._state = "running";
l.blank(1);
Object.entries(webpackExportModules).forEach(([ n, m ]) => { exportConfig(n, m, build, wpc); });
Object.keys(build.wpc).forEach((k) => { if (isEmpty(build.wpc[k])) { delete build.wpc[k]; }});
printBuildProperties(build, undefined, " ");
l.success(`successfully configured webpack exports for build '${this.name}'`, 1, lPad);
l.blank(1);
return wpc;
}
catch (e)
{ l.error("dump invalid configuration:");
printBuildProperties(build, withColor(l.icons.error, l.color), "");
l.blank(1, withColor(l.icons.error, l.color));
throw e;
}
}
module.exports = webpackExports;
module.exports.webpackExportModules = webpackExportModules;