"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigureWebpackTask = exports.FILE_LOADER_EXTENSIONS = void 0;
const path = __importStar(require("path"));
const spfx_heft_plugins_1 = require("@microsoft/spfx-heft-plugins");
const node_core_library_1 = require("@rushstack/node-core-library");
const OdspGulpTask_1 = require("../OdspGulpTask");
const GulpTaskTerminalProvider_1 = require("../utilities/GulpTaskTerminalProvider");
exports.FILE_LOADER_EXTENSIONS = ['jpg', 'png', 'woff', 'eot', 'ttf', 'svg', 'gif', 'dds'];
const UPGRADE_PARAM_NAME = 'upgrade';
/**
 * Configures the @microsoft/gulp-core-build-webpack task with some smart defaults based on the package configuration.
 */
class ConfigureWebpackTask extends OdspGulpTask_1.OdspGulpTask {
    constructor() {
        super('configure-webpack', {
            libraryName: undefined,
            webpack: undefined,
            additionalConfiguration: undefined
        });
    }
    loadSchema() {
        return node_core_library_1.JsonFile.load(path.join(__dirname, 'configure-webpack.schema.json'));
    }
    setConfig(config) {
        if (config.webpack && config.webpack.name !== 'webpack') {
            this.logWarning('Setting webpack property to non-"@microsoft/gulp-core-build-webpack"-type will ' +
                'prevent configuration');
        }
        super.mergeConfig(config);
    }
    async executeTask() {
        if (!this.taskConfig.webpack) {
            this.logWarning('"webpack" is not defined in the task configuration. Nothing to configure.');
            return;
        }
        const configJson = this._getConfigJson();
        const terminal = new node_core_library_1.Terminal(new GulpTaskTerminalProvider_1.GulpTaskTerminalProvider(this));
        let legacyExternals;
        if (this.taskConfig.useLegacyExternals) {
            legacyExternals = new spfx_heft_plugins_1._LegacyExternals({
                terminal,
                singleLocale: this.taskConfig.singleLocale,
                configJson: configJson,
                buildFolder: this.buildConfig.rootPath,
                serveMode: !!this.properties.serveMode,
                production: this.buildConfig.production
            });
        }
        const packageJson = node_core_library_1.PackageJsonLookup.instance.tryLoadPackageJsonFor(this.buildConfig.rootPath);
        if (!packageJson) {
            throw new Error('Unable to find package.json. Was the tool invoked in a project folder?');
        }
        let config = (await spfx_heft_plugins_1.WebpackConfigurationGenerator.generateWebpackConfigurationAsync({
            configJson: configJson,
            folders: {
                buildFolder: this.buildConfig.rootPath,
                tempFolder: path.join(this.buildConfig.rootPath, 'temp'),
                releaseFolder: path.join(this.buildConfig.rootPath, 'release'),
                outputFolder: path.join(this.buildConfig.rootPath, 'dist')
            },
            terminal,
            production: this.buildConfig.production,
            serveMode: !!this.properties.serveMode,
            projectPackageJson: packageJson,
            getLocalization: this.taskConfig.getLocalization,
            singleLocale: this.taskConfig.singleLocale,
            linkedExternalsToBundle: this.taskConfig.linkedExternalsToBundle,
            libraryName: this.taskConfig.libraryName,
            libraryTarget: this.taskConfig.libraryTarget,
            disableAsyncComponentLoading: this.taskConfig.disableAsyncComponentLoading,
            assetsAreVersioned: this.taskConfig.assetsAreVersioned,
            loadThemedStylesImportPath: this.taskConfig.loadThemedStylesImportPath,
            generateCssClassName: this.taskConfig.generateCssClassName,
            releaseManifestFolderName: this.taskConfig.releaseManifestFolderName
        }));
        if (config) {
            this.taskConfig.webpack.isEnabled = () => true;
            legacyExternals === null || legacyExternals === void 0 ? void 0 : legacyExternals.updateWebpackConfiguration(config);
            if (this.taskConfig.additionalConfiguration) {
                config = this.taskConfig.additionalConfiguration(config);
            }
        }
        else {
            this.taskConfig.webpack.isEnabled = () => false;
        }
        this._setWebpackConfig(config);
    }
    _setWebpackConfig(config) {
        const webpackTask = this.taskConfig.webpack;
        const sourceMapWarningSuppression = /Cannot find SourceMap \'.+\'\: Error\:/;
        // Disable Performance hints.
        const performanceHintSuppression = /(asset|entrypoint) size limit.*/;
        const performanceRecommendationSuppression = /webpack performance recommendations.*/;
        const suppressedWarnings = webpackTask.taskConfig.suppressWarnings || [];
        if (webpackTask) {
            webpackTask.setConfig({
                config: config,
                configPath: null,
                suppressWarnings: suppressedWarnings.concat([
                    sourceMapWarningSuppression,
                    performanceHintSuppression,
                    performanceRecommendationSuppression
                ])
            });
        }
    }
    _getConfigJson() {
        const configFilePath = path.join(this.buildConfig.rootPath, 'config', 'config.json');
        const configResult = (0, spfx_heft_plugins_1._readConfigFile)(this.logVerbose.bind(this), configFilePath);
        if (configResult.missingFile) {
            this.logWarning('Missing config.json file. If this is a non-web project, consider using a non-web build rig ' +
                'like @microsoft/sp-build-node');
        }
        if (configResult.readError) {
            throw new Error(`Error reading config.json file: ${configResult.readError}`);
        }
        if (!configResult.isLatestVersion) {
            if (this.buildConfig.args[UPGRADE_PARAM_NAME]) {
                (0, spfx_heft_plugins_1._migrateToLatestVersion)(this.logWarning.bind(this), configResult.configData);
                node_core_library_1.JsonFile.save(configResult.configData, configFilePath, { prettyFormatting: true });
            }
            else {
                this.logWarning(`This project is using an old config.json file version (${configResult.version}). Run the ` +
                    `build again with the --${UPGRADE_PARAM_NAME} (gulp --${UPGRADE_PARAM_NAME}) flag to ` +
                    'upgrade the config.json file to the latest version.');
            }
        }
        return configResult.configData;
    }
}
exports.ConfigureWebpackTask = ConfigureWebpackTask;
//# sourceMappingURL=ConfigureWebpackTask.js.map