"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.onRollupWarning = exports.build = exports.resolveBuildPlugins = exports.resolveBuildOptions = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const chalk_1 = __importDefault(require("chalk"));
const config_1 = require("./config");
const reporter_1 = require("./plugins/reporter");
const define_1 = require("./plugins/define");
const html_1 = require("./plugins/html");
const esbuild_1 = require("./plugins/esbuild");
const terser_1 = require("./plugins/terser");
const utils_1 = require("./utils");
const manifest_1 = require("./plugins/manifest");
const plugin_commonjs_1 = __importDefault(require("@rollup/plugin-commonjs"));
const plugin_dynamic_import_vars_1 = __importDefault(require("@rollup/plugin-dynamic-import-vars"));
const isbuiltin_1 = __importDefault(require("isbuiltin"));
const slash_1 = __importDefault(require("slash"));
function resolveBuildOptions(raw) {
    const resolved = {
        base: '/',
        target: 'es2019',
        outDir: 'dist',
        assetsDir: 'assets',
        assetsInlineLimit: 4096,
        getPublicHash: () => null,
        cssCodeSplit: !(raw === null || raw === void 0 ? void 0 : raw.lib),
        sourcemap: false,
        rollupOptions: {},
        minify: 'terser',
        terserOptions: {},
        cleanCssOptions: {},
        write: true,
        manifest: false,
        lib: false,
        ssr: false,
        ...raw
    };
    // ensure base ending slash
    resolved.base = resolved.base.replace(/([^/])$/, '$1/');
    // normalize false string into actual false
    if (resolved.minify === 'false') {
        resolved.minify = false;
    }
    return resolved;
}
exports.resolveBuildOptions = resolveBuildOptions;
function resolveBuildPlugins(config) {
    const options = config.build;
    return {
        pre: [
            plugin_commonjs_1.default({
                include: [/node_modules/],
                extensions: ['.js', '.cjs']
            }),
            html_1.buildHtmlPlugin(config),
            define_1.buildDefinePlugin(config),
            plugin_dynamic_import_vars_1.default({
                warnOnError: true,
                exclude: [/node_modules/]
            }),
            ...(options.rollupOptions.plugins || [])
        ],
        post: [
            esbuild_1.buildEsbuildPlugin(config),
            ...(options.minify && options.minify !== 'esbuild'
                ? [terser_1.terserPlugin(options.terserOptions)]
                : []),
            ...(options.manifest ? [manifest_1.manifestPlugin()] : []),
            ...(!config.logLevel || config.logLevel === 'info'
                ? [reporter_1.buildReporterPlugin(config)]
                : [])
        ]
    };
}
exports.resolveBuildPlugins = resolveBuildPlugins;
/**
 * Track parallel build calls and only stop the esbuild service when all
 * builds are done. (#1098)
 */
let parallelCallCounts = 0;
// we use a separate counter to track since the call may error before the
// bundle is even pushed.
const paralellBuilds = [];
/**
 * Bundles the app for production.
 * Returns a Promise containing the build result.
 */
async function build(inlineConfig = {}, configPath) {
    parallelCallCounts++;
    try {
        return await doBuild(inlineConfig, configPath);
    }
    finally {
        parallelCallCounts--;
        if (parallelCallCounts <= 0) {
            paralellBuilds.forEach((bundle) => bundle.close());
            paralellBuilds.length = 0;
        }
    }
}
exports.build = build;
async function doBuild(inlineConfig = {}, configPath) {
    var _a, _b;
    const mode = inlineConfig.mode || 'production';
    const config = await config_1.resolveConfig(inlineConfig, 'build', mode, configPath);
    config.logger.info(chalk_1.default.cyan(`building for production...`));
    const options = config.build;
    const libOptions = options.lib;
    const resolve = (p) => path_1.default.resolve(config.root, p);
    const input = libOptions
        ? libOptions.entry
        : ((_a = options.rollupOptions) === null || _a === void 0 ? void 0 : _a.input) || resolve('index.html');
    const outDir = resolve(options.outDir);
    const publicDir = resolve('public');
    if (options.write) {
        utils_1.emptyDir(outDir);
        if (fs_1.default.existsSync(publicDir)) {
            const { getPublicHash } = options;
            const dirs = new Set();
            const ensureDir = (dir) => dirs.has(dir) || (dirs.add(dir), fs_1.default.mkdirSync(dir, { recursive: true }));
            utils_1.crawlDir(publicDir, (file, name, parent) => {
                const srcFile = path_1.default.join(publicDir, file);
                const assetHash = getPublicHash(srcFile);
                let outFile = file;
                if (assetHash) {
                    const assetExt = path_1.default.extname(name);
                    outFile = file.slice(0, -assetExt.length) + '.' + assetHash + assetExt;
                }
                ensureDir(path_1.default.join(outDir, parent));
                fs_1.default.copyFileSync(srcFile, path_1.default.join(outDir, outFile));
                config.publicUrls['/' + slash_1.default(file)] = '/' + slash_1.default(outFile);
            });
        }
    }
    const rollup = require('rollup');
    try {
        const bundle = await rollup.rollup({
            input,
            preserveEntrySignatures: libOptions ? 'strict' : false,
            ...options.rollupOptions,
            plugins: config.plugins,
            onwarn(warning, warn) {
                var _a;
                onRollupWarning(warning, warn, [], (_a = options.rollupOptions) === null || _a === void 0 ? void 0 : _a.onwarn);
            }
        });
        paralellBuilds.push(bundle);
        const pkgName = libOptions &&
            JSON.parse(utils_1.lookupFile(config.root, ['package.json']) || `{}`).name;
        const generate = (output = {}) => {
            return bundle[options.write ? 'write' : 'generate']({
                dir: outDir,
                format: 'es',
                exports: 'auto',
                sourcemap: options.sourcemap,
                name: libOptions ? libOptions.name : undefined,
                entryFileNames: libOptions
                    ? `${pkgName}.${output.format || `es`}.js`
                    : path_1.default.posix.join(options.assetsDir, `[name].[hash].js`),
                chunkFileNames: libOptions
                    ? `[name].js`
                    : path_1.default.posix.join(options.assetsDir, `[name].[hash].js`),
                assetFileNames: libOptions
                    ? `[name].[ext]`
                    : path_1.default.posix.join(options.assetsDir, `[name].[hash].[ext]`),
                // #764 add `Symbol.toStringTag` when build es module into cjs chunk
                // #1048 add `Symbol.toStringTag` for module default export
                namespaceToStringTag: true,
                ...output
            });
        };
        // resolve lib mode outputs
        const outputs = resolveBuildOutputs((_b = options.rollupOptions) === null || _b === void 0 ? void 0 : _b.output, libOptions, config.logger);
        if (Array.isArray(outputs)) {
            const res = [];
            for (const output of outputs) {
                res.push(await generate(output));
            }
            return res;
        }
        else {
            return generate(outputs);
        }
    }
    catch (e) {
        config.logger.error(chalk_1.default.red(`${e.plugin ? `[${e.plugin}] ` : ``}${e.message}`));
        if (e.id) {
            const loc = e.loc ? `:${e.loc.line}:${e.loc.column}` : ``;
            config.logger.error(`file: ${chalk_1.default.cyan(`${e.id}${loc}`)}`);
        }
        if (e.frame) {
            config.logger.error(chalk_1.default.yellow(e.frame));
        }
        throw e;
    }
}
function resolveBuildOutputs(outputs, libOptions, logger) {
    if (libOptions) {
        const formats = libOptions.formats || ['es', 'umd'];
        if ((formats.includes('umd') || formats.includes('iife')) &&
            !libOptions.name) {
            throw new Error(`Option "build.lib.name" is required when output formats ` +
                `include "umd" or "iife".`);
        }
        if (!outputs) {
            return formats.map((format) => ({ format }));
        }
        else if (!Array.isArray(outputs)) {
            return formats.map((format) => ({ ...outputs, format }));
        }
        else if (libOptions.formats) {
            // user explicitly specifying own output array
            logger.warn(chalk_1.default.yellow(`"build.lib.formats" will be ignored because ` +
                `"build.rollupOptions.output" is already an array format`));
        }
    }
    return outputs;
}
const warningIgnoreList = [`CIRCULAR_DEPENDENCY`, `THIS_IS_UNDEFINED`];
const dynamicImportWarningIgnoreList = [
    `Unsupported expression`,
    `statically analyzed`
];
function onRollupWarning(warning, warn, allowNodeBuiltins = [], userOnWarn) {
    function doWarn() {
        if (userOnWarn) {
            userOnWarn(warning, warn);
        }
        else {
            warn(warning);
        }
    }
    if (warning.code === 'UNRESOLVED_IMPORT') {
        let message;
        const id = warning.source;
        const importer = warning.importer;
        if (importer && /\?commonjs-external$/.test(importer)) {
            // allow commonjs external...
            warning.message = chalk_1.default.yellow(warning.message);
            return doWarn();
        }
        if (id && isbuiltin_1.default(id)) {
            let importingDep;
            if (importer) {
                const pkg = JSON.parse(utils_1.lookupFile(importer, ['package.json']) || `{}`);
                if (pkg.name) {
                    importingDep = pkg.name;
                }
            }
            if (importingDep &&
                allowNodeBuiltins.some((allowed) => importingDep.startsWith(allowed))) {
                return;
            }
            const dep = importingDep
                ? `Dependency ${chalk_1.default.yellow(importingDep)}`
                : `A dependency`;
            message =
                `${dep} is attempting to import Node built-in module ${chalk_1.default.yellow(id)}.\n` +
                    `This will not work in a browser environment.\n` +
                    `Imported by: ${chalk_1.default.gray(importer)}`;
        }
        else {
            message =
                `[vite]: Rollup failed to resolve import "${warning.source}" from "${warning.importer}".\n` +
                    `This is most likely unintended because it can break your application at runtime.\n` +
                    `If you do want to externalize this module explicitly add it to\n` +
                    `\`build.rollupOptions.external\``;
        }
        throw new Error(message);
    }
    if (warning.plugin === 'rollup-plugin-dynamic-import-variables' &&
        dynamicImportWarningIgnoreList.some((msg) => warning.message.includes(msg))) {
        return;
    }
    if (!warningIgnoreList.includes(warning.code)) {
        doWarn();
    }
}
exports.onRollupWarning = onRollupWarning;
//# sourceMappingURL=build.js.map