"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 = exports.buildWedaConfig = 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 common_2 = require("../../utils/common");
const postProcess_1 = require("../../utils/postProcess");
const cals_1 = require("@cloudbase/cals");
const net_1 = require("../util/net");
const config_1 = require("../config");
const pkg = require('../../../package.json');
async function buildWedaConfig({ output, domain = undefined, isPrivateMode = undefined, endpointType = undefined, buildTypeList = [common_1.BuildType.WEB], }) {
    if ((0, common_1.buildAsWebByBuildType)(buildTypeList)) {
        throw new Error('构建类型仅支持 MP');
    }
    let outDir = output === null || output === void 0 ? void 0 : output.path;
    if (!outDir) {
        throw new Error('无效的项目输出路径');
    }
    let miniprogramRoot = outDir;
    let projectJsonPath = path_1.default.resolve(outDir, 'project.config.json');
    if (fs_extra_1.default.existsSync(projectJsonPath)) {
        const projectConfigJson = await fs_extra_1.default.readJson(projectJsonPath);
        miniprogramRoot = path_1.default.join(outDir, projectConfigJson.miniprogramRoot || '/');
    }
    const configPath = path_1.default.resolve(miniprogramRoot, 'common/config.js');
    let data = { domain, isPrivateMode, endpointType };
    if (fs_extra_1.default.existsSync(configPath)) {
        try {
            let config = require(configPath);
            let current = {};
            if (config.__esModule) {
                current = config.default || {};
            }
            else {
                current = config || {};
            }
            for (const key in data) {
                if (data[key] === undefined) {
                    data[key] = current[key];
                }
            }
        }
        catch (e) {
            console.error('parse current file error, overwrite current config', e);
        }
    }
    await (0, index_1.generateConfig)(data, outDir);
}
exports.buildWedaConfig = buildWedaConfig;
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, enableExpiredTag = false, account = {}, }, cb) {
    var _a, _b, _c, _d, _e, _f;
    if (!cals) {
        console.error('无效的应用配置');
        return;
    }
    if (!deployOptions.mode) {
        deployOptions.mode = types_1.DEPLOY_MODE.PREVIEW;
    }
    /**
     * 刷新正规化 packageName
     */
    [cals, ...subAppCalsList].forEach((app) => {
        if (!app.extra) {
            app.extra = {};
        }
        app.extra.rootPath = (0, util_1.normalizePackageName)(app.extra.rootPath);
    });
    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 = {
        uin: account === null || account === void 0 ? void 0 : account.uin,
        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,
        enableExpiredTag,
        disabled: (_c = cals.extra) === null || _c === void 0 ? void 0 : _c.disabled,
        statusPageId: (_d = cals.extra) === null || _d === void 0 ? void 0 : _d.statusPageId,
    };
    console.log('domain', domain);
    console.log('应用名', appKey);
    console.log('生成模式', generateMpType);
    console.log('生成路径', appBuildDir);
    try {
        const startTime = Date.now();
        function processRepeaterDisplay(cals) {
            cals.items = (cals.items || []).map((page) => {
                return JSON.parse(JSON.stringify(page, (key, value) => {
                    if ((value === null || value === void 0 ? void 0 : value.component) && !(value === null || value === void 0 ? void 0 : value.module) && (value === null || value === void 0 ? void 0 : value.type) !== 'PAGE') {
                        value.module = cals_1.OFFICIAL_LIB_KEY;
                    }
                    if (value === null || value === void 0 ? void 0 : value.component) {
                        const component = value;
                        if ((value === null || value === void 0 ? void 0 : value.component) &&
                            `${component.module}:${component.component}` === `${config_1.REPEATER.MODULE_NAME}:${config_1.REPEATER.REPEATER_NAME}`) {
                            // 给 Repeater 组件加一层虚拟项组件，在虚拟项组件上挂 for 循环
                            const { items = [] } = component;
                            component.items = items.map((item) => {
                                var _a;
                                let currentDisplay = (_a = component === null || component === void 0 ? void 0 : component.directives) === null || _a === void 0 ? void 0 : _a[':display'];
                                if (currentDisplay !== undefined && currentDisplay !== 'true') {
                                    if (!item.directives) {
                                        item.directives = {};
                                    }
                                    const current = item.directives[':display'] || 'true';
                                    item.directives[':display'] = `(\n${currentDisplay}\n) && (\n${current}\n)`;
                                }
                                return item;
                            });
                        }
                    }
                    return value;
                }));
            });
            return cals;
        }
        if (buildTypeList.includes(common_1.BuildType.MP)) {
            const mainAppSerializeData = (0, common_2.processCals2WeappsData)(processRepeaterDisplay(cals), dependencies);
            const subAppSerializeDataList = (subAppCalsList === null || subAppCalsList === void 0 ? void 0 : subAppCalsList.map((item) => (0, common_2.processCals2WeappsData)(processRepeaterDisplay(item), dependencies))) || [];
            const apps = [mainAppSerializeData, ...subAppSerializeDataList];
            const calses = [cals, ...subAppCalsList];
            if (isBrowserMpBuilder) {
                // 尽早下载物料
                await (0, net_1.downloadBrowserMaterial)(output === null || output === void 0 ? void 0 : output.path);
            }
            const { enablePageRoot } = (0, cals_1.parseVersion)(cals === null || cals === void 0 ? void 0 : cals.schemaVersion, dependencies);
            const mpBuildContext = {
                ...buildContext,
                projDir: (output === null || output === void 0 ? void 0 : output.path) || path_1.default.join(appBuildDir, 'mp'),
                mainAppData: mainAppSerializeData,
                processCssUnit: (calses.find((cals) => {
                    const FEATURE_MAP = (0, cals_1.parseVersion)(cals.schemaVersion, dependencies);
                    return !FEATURE_MAP.defaultDynamicCssUnit;
                })
                    ? 'px'
                    : 'rpx'),
                enablePageRoot,
                enableLoading: (_e = cals === null || cals === void 0 ? void 0 : cals.extra) === null || _e === void 0 ? void 0 : _e.enableLoading,
                enableAsyncMaterials: (_f = cals.extra) === null || _f === void 0 ? void 0 : _f.enableAsyncMaterials,
                // enableAsyncMaterials: true,
            };
            const result = await (0, index_1.generateWxMp)({
                weapps: apps,
                calses,
                buildContext: mpBuildContext,
                plugins,
                deployOptions,
                options: {
                    isCrossAccount: resourceAppId !== deployOptions.targetMpAppId,
                    mpAppId: deployOptions.mpAppId || '',
                    resourceAppId,
                },
                buildTypeList,
                ignoreInstall,
                cdnEndpoints: (0, config_1.generateCdnEndpoints)(cdnEndpoints),
            });
            // 如果是混合模式，则将特定的目录复制到工程下
            // 针对 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 {
            // web worker build 构建时注入, H5构建目前不支持web worker，web worker build时过滤掉
            if (!process.env.IS_WEB_WORKER) {
                const { buildH5App } = require('../h5/index');
                const h5BuildDir = await buildH5App({
                    buildContext: { ...buildContext, isMixMode: false },
                    cals,
                    subAppCalsList,
                    extraData,
                    buildTypeList,
                    mode,
                    devTool,
                    runtime,
                    deployOptions,
                    ignoreInstall,
                    cdnEndpoints: (0, config_1.generateCdnEndpoints)(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.UPLOAD ? `/${appId}/production/` : `/${appId}/preview/`;
}
