"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeInputs = exports.getCompileDirs = exports.downloadZip = exports.strToBuf = exports.fileToZip = exports.getFiles = exports.version = exports.cleanComponentDir = exports.buildWedaApp = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const chalk_1 = __importDefault(require("chalk"));
const path_1 = __importDefault(require("path"));
const util_1 = require("../util");
const common_1 = require("../types/common");
const index_1 = require("../mp/index");
const types_1 = require("../../types");
const mixMode_1 = require("../mp/mixMode");
const index_2 = require("../h5/index");
const common_2 = require("../../utils/common");
const postProcess_1 = require("../../utils/postProcess");
const net_1 = require("../util/net");
const pkg = require('../../../package.json');
async function buildWedaApp({ cals, subAppCalsList = [], dependencies = [], appKey = 'test', runtime = types_1.RUNTIME.NONE, ignoreInstall = false, buildTypeList = [common_1.BuildType.WEB], mode = common_1.WebpackModeType.PRODUCTION, devTool = 'webpack', deployOptions = { mode: types_1.DEPLOY_MODE.PREVIEW }, generateMpType = common_1.GenerateMpType.APP, plugins = [], extraData = {
    isComposite: false,
    compProps: {},
}, resourceAppId = undefined, domain = '', output, isBrowserMpBuilder = false, cdnEndpoints, isPrivateMode = false, endpointType = undefined, }, cb) {
    var _a, _b;
    if (!cals) {
        console.error('无效的应用配置');
        return;
    }
    const { mode: deployMode = types_1.DEPLOY_MODE.PREVIEW } = deployOptions;
    let appBuildDir = (output === null || output === void 0 ? void 0 : output.path) || (runtime === types_1.RUNTIME.CI ? (_a = (0, util_1.getCompileDirs)('app')) === null || _a === void 0 ? void 0 : _a.appBuildDir : (_b = (0, util_1.getCompileDirs)(appKey)) === null || _b === void 0 ? void 0 : _b.appBuildDir);
    const buildContext = {
        projDir: appBuildDir,
        appId: appKey,
        isProduction: mode === common_1.WebpackModeType.PRODUCTION,
        materialLibs: dependencies,
        debugMode: mode !== common_1.WebpackModeType.PRODUCTION && !!process.env.WEAPPS_DEBUG,
        isMixMode: generateMpType === common_1.GenerateMpType.SUBPACKAGE,
        domain,
        isBrowserMpBuilder,
        isPrivateMode,
        endpointType,
    };
    console.log('domain', domain);
    console.log('应用名', appKey);
    console.log('生成模式', generateMpType);
    console.log('生成路径', appBuildDir);
    try {
        const startTime = Date.now();
        if (buildTypeList.includes(common_1.BuildType.MP)) {
            const mainAppSerializeData = (0, common_2.processCals2WeappsData)(cals, dependencies);
            const subAppSerializeDataList = (subAppCalsList === null || subAppCalsList === void 0 ? void 0 : subAppCalsList.map((item) => (0, common_2.processCals2WeappsData)(item, dependencies))) || [];
            const apps = [mainAppSerializeData, ...subAppSerializeDataList];
            if (isBrowserMpBuilder) {
                // 尽早下载物料
                await (0, net_1.downloadBrowserMaterial)(output === null || output === void 0 ? void 0 : output.path);
            }
            const mpBuildContext = {
                ...buildContext,
                projDir: (output === null || output === void 0 ? void 0 : output.path) || path_1.default.join(appBuildDir, 'mp'),
                mainAppData: mainAppSerializeData,
            };
            const result = await (0, index_1.generateWxMp)({
                weapps: apps,
                buildContext: mpBuildContext,
                plugins,
                deployMode,
                options: {
                    isCrossAccount: resourceAppId !== deployOptions.targetMpAppId,
                    mpAppId: deployOptions.mpAppId || '',
                    resourceAppId,
                },
                buildTypeList,
                isBrowserMpBuilder,
                ignoreInstall,
            });
            // 如果是混合模式，则将特定的目录复制到工程下
            // 针对 app.json / package.json 则采用 merge 的操作
            if (buildContext.isMixMode) {
                console.log(chalk_1.default.green('【混合模式】'), mpBuildContext.projDir);
                await (0, mixMode_1.handleMixMode)({
                    buildContext: mpBuildContext,
                    apps,
                    miniprogramRoot: result.miniprogramRoot,
                    plugins,
                    ignoreInstall,
                });
            }
            const outDir = mpBuildContext.projDir;
            let projectJsonPath = path_1.default.resolve(outDir, 'project.config.json');
            await (0, postProcess_1.postprocessProjectConfig)(projectJsonPath, {
                appid: deployOptions === null || deployOptions === void 0 ? void 0 : deployOptions.mpAppId,
                cloudfunctionRoot: undefined,
            });
            // 如果是代开发的模式，则写入ext.json
            await (0, postProcess_1.postprocessDeployExtraJson)(outDir, deployOptions);
            if (!isBrowserMpBuilder && generateMpType === common_1.GenerateMpType.APP && !ignoreInstall) {
                // 模板拷入的 miniprogram_npm 有问题，直接删除使用重新构建的版本
                // 模板需要占位保证 mp 文件夹存在
                fs_extra_1.default.removeSync(path_1.default.resolve(outDir, 'miniprogram_npm'));
            }
            await (cb === null || cb === void 0 ? void 0 : cb(null, {
                ...result,
                outDir,
                timeElapsed: Date.now() - startTime,
            }));
            return outDir;
        }
        else {
            const h5BuildDir = await (0, index_2.buildH5App)({
                buildContext: { ...buildContext, isMixMode: false },
                cals,
                subAppCalsList,
                extraData,
                buildTypeList,
                mode,
                devTool,
                runtime,
                deployMode,
                ignoreInstall,
                cdnEndpoints,
            });
            await (cb === null || cb === void 0 ? void 0 : cb(null, {
                outDir: h5BuildDir,
                timeElapsed: Date.now() - startTime,
            }));
            return h5BuildDir;
        }
    }
    catch (err) {
        if (err.length) {
            let messageList = (err[0] || '').split('\n');
            let lineIndex = 0;
            let reg = /node_modules\/@babel/;
            messageList.find((str, index) => {
                if (reg.test(str)) {
                    lineIndex = index;
                    return true;
                }
                else {
                    return false;
                }
            });
            if (lineIndex) {
                messageList = messageList.slice(0, lineIndex);
            }
            err = new Error(messageList.join('\n'));
        }
        cb === null || cb === void 0 ? void 0 : cb(err);
        throw err;
    }
}
exports.buildWedaApp = buildWedaApp;
async function cleanComponentDir() {
    return fs_extra_1.default.emptyDir((0, util_1.getCompileDirs)().materialsDir);
}
exports.cleanComponentDir = cleanComponentDir;
exports.version = pkg.version;
var generateFiles_1 = require("../util/generateFiles");
Object.defineProperty(exports, "getFiles", { enumerable: true, get: function () { return generateFiles_1.getFiles; } });
Object.defineProperty(exports, "fileToZip", { enumerable: true, get: function () { return generateFiles_1.fileToZip; } });
Object.defineProperty(exports, "strToBuf", { enumerable: true, get: function () { return generateFiles_1.strToBuf; } });
var net_2 = require("../util/net");
Object.defineProperty(exports, "downloadZip", { enumerable: true, get: function () { return net_2.downloadZip; } });
var util_2 = require("../util");
Object.defineProperty(exports, "getCompileDirs", { enumerable: true, get: function () { return util_2.getCompileDirs; } });
exports.default = buildWedaApp;
function normalizeInputs(inputs, { envId, getWebRootPath, }) {
    const { extraData = { isComposite: false, compProps: {} } } = inputs;
    /**
     * 过滤处理 dependencies
     */
    let map = {};
    inputs.dependencies = (inputs.dependencies || []).reduce((list, item) => {
        if (!map[`${item.name}@${item.version}`]) {
            map[`${item.name}@${item.version}`] = true;
            list.push(item);
        }
        return list;
    }, []);
    const normalizeCalsOptions = {
        buildTypeList: inputs.buildTypeList,
        envId,
        deployOptions: inputs.deployOptions,
        appId: inputs.appId || inputs.appKey,
        getWebRootPath: getWebRootPath || _getWebRootPath,
    };
    if (inputs.mainAppSerializeData) {
        inputs.mainAppSerializeData = normalizeCals(inputs.mainAppSerializeData, normalizeCalsOptions);
        if ((0, common_1.buildAsWebByBuildType)(inputs.buildTypeList)) {
            inputs.subAppSerializeDataList = [];
        }
    }
    if (inputs.cals) {
        inputs.cals = normalizeCals(inputs.cals, normalizeCalsOptions);
        if ((0, common_1.buildAsWebByBuildType)(inputs.buildTypeList)) {
            inputs.subAppCalsList = [];
        }
    }
    if (!(0, common_1.buildAsWebByBuildType)(inputs.buildTypeList)) {
        // 小程序构建
        const { mpAppId, deployOptions = { mode: types_1.DEPLOY_MODE.PREVIEW } } = inputs;
        inputs.deployOptions = {
            ...deployOptions,
            mpAppId: deployOptions.mpAppId || mpAppId,
        };
        if (!inputs.deployOptions.targetMpAppId) {
            inputs.deployOptions.targetMpAppId = inputs.deployOptions.mpAppId;
        }
    }
    if (extraData.isComposite) {
        Object.keys(extraData.compProps.events).forEach((eName) => {
            extraData.compProps.events[eName] = `$$EVENT_${eName}$$`;
        });
    }
    return inputs;
}
exports.normalizeInputs = normalizeInputs;
function normalizeCals(cals, { buildTypeList, envId, deployOptions, appId, getWebRootPath }) {
    var _a, _b;
    if (!cals.extra) {
        cals.extra = {};
    }
    if (!cals.mpPkgUrl) {
        if (buildTypeList.includes(common_1.BuildType.APP) ||
            buildTypeList.includes(common_1.BuildType.XPAGE_PC) ||
            buildTypeList.includes(common_1.BuildType.ADMIN_PORTAL)) {
            cals.extra.historyType = types_1.HISTORY_TYPE.HASH;
        }
    }
    if (!((_a = cals === null || cals === void 0 ? void 0 : cals.extra) === null || _a === void 0 ? void 0 : _a.envId)) {
        cals.extra.envId = envId;
    }
    if ((0, common_1.buildAsWebByBuildType)(buildTypeList)) {
        // web 构建不处理小程序插件
        if (cals.extra.miniprogramPlugins) {
            cals.extra.miniprogramPlugins = [];
        }
        let { appConfig = {} } = cals.extra;
        let { window = {} } = appConfig;
        let path = getWebRootPath({ appId, deployOptions });
        cals.extra.appConfig = {
            ...appConfig,
            window: {
                ...window,
                // Todo: 处理自定义域名逻辑
                publicPath: (0, common_1.buildAsXPageByBuildType)(buildTypeList)
                    ? (deployOptions === null || deployOptions === void 0 ? void 0 : deployOptions.publicPath) || `https://${(_b = cals.extra) === null || _b === void 0 ? void 0 : _b.domain}${path}`
                    : path,
                basename: (0, common_1.buildAsAdminPortalByBuildType)(buildTypeList)
                    ? `app/${appId}${(deployOptions === null || deployOptions === void 0 ? void 0 : deployOptions.mode) !== types_1.DEPLOY_MODE.UPLOAD ? '-preview' : ''}`
                    : (0, common_1.buildAsXPageByBuildType)(buildTypeList)
                        ? '/'
                        : path,
            },
        };
    }
    return cals;
}
function _getWebRootPath({ appId, deployOptions }) {
    return (deployOptions === null || deployOptions === void 0 ? void 0 : deployOptions.mode) === types_1.DEPLOY_MODE.PREVIEW ? `/${appId}/preview/` : `/${appId}/production/`;
}
