UNPKG

youzanyun-devtool-worker

Version:

- web - ws - proxy

297 lines (296 loc) 12.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const path_1 = tslib_1.__importDefault(require("path")); const axios_1 = tslib_1.__importDefault(require("axios")); const fs_extra_1 = tslib_1.__importDefault(require("fs-extra")); const spring4js_nodejs_1 = require("spring4js-nodejs"); let ActionHtmlModifyService = class ActionHtmlModifyService { async getCachePreviewComps(projectId, url) { try { const result = await axios_1.default.request({ method: 'GET', url: 'http://127.0.0.1:31240/api/h5-extension/getPreviewComps', params: { projectId, url }, }); return result.data.data || []; } catch (err) { return {}; } } async processRequest(ctx, next) { const { mall_cloud: pageName, nodeName, proPath } = ctx.query; if (ctx.path === '/html/h5-replace-preview') { await this.pageReplace(ctx, next); } else if (pageName && nodeName && proPath) { if (ctx.path === '/wscgoods/detail-api/init.jsonp') { return false; } else if (ctx.path === '/wscgoods/detail-api/cloud.jsonp') { await this.sandBoxPageModify(ctx, next); } else { await this.pageModify(ctx, next); } } else { return false; } return true; } async pageReplace(ctx, next) { const { realMode, pagePath } = ctx.query; let requestHeader = ctx.headers; requestHeader['accept-encoding'] = 'gzip, deflate'; let axiosRes = await axios_1.default.request({ method: ctx.method, url: ctx.href, headers: requestHeader, data: ctx.isJsonHeader ? ctx.request.body : ctx.req, }); const jsPath = `${pagePath}/index.js`; const cssPath = `${pagePath}/index.css`; let tempData = axiosRes.data; let index = tempData.indexOf('<div id="jsReplace"></div>'); tempData = tempData.slice(0, index) + `<script src="/_yzydev_/local/file?filePath=${jsPath}"></script>` + tempData.slice(index); index = tempData.indexOf('</head>'); tempData = tempData.slice(0, index) + `<link rel="stylesheet" type="text/css" href="/_yzydev_/local/file?filePath=${cssPath}" />` + tempData.slice(index); axiosRes.data = tempData; let header = JSON.parse(JSON.stringify(axiosRes.headers)); delete header["content-length"]; ctx.set(header); ctx.body = axiosRes.data; } async getLocalComponent(proPath, nodeName, pageName) { let result = { localComps: null, localPageFile: '' }; const distPath = path_1.default.resolve(proPath, "dist"); const infoPath = path_1.default.resolve(distPath, "info.json"); let info = null; if (fs_extra_1.default.existsSync(infoPath)) { info = await fs_extra_1.default.readJson(infoPath); } if (info) { let comps = []; let localPageName = ''; if (info[pageName]) { comps = info[pageName].components; localPageName = pageName; } else if (info[nodeName]) { comps = info[nodeName].components; localPageName = nodeName; } else if (info["_global"]) { comps = info["_global"].components; localPageName = "_global"; } result.localComps = comps.map((item) => ({ type: item.name, title: item.title })); let pageFiles = await fs_extra_1.default.readdir(distPath); pageFiles = pageFiles.filter(v => v !== "info.json" && v.indexOf(localPageName) !== -1 && !v.endsWith('.map')); result.localPageFile = pageFiles[0]; } return result; } async sandBoxPageModify(ctx, next) { const { mall_cloud: pageName, nodeName, proPath, projectId, workbenchId, refUrl } = ctx.query; let requestHeader = JSON.parse(JSON.stringify(ctx.headers)); requestHeader['accept-encoding'] = 'gzip, deflate'; let axiosRes = await axios_1.default.request({ method: ctx.method, url: ctx.href, headers: requestHeader, data: ctx.isJsonHeader ? ctx.request.body : ctx.req, responseType: "text", validateStatus: function (status) { return true; }, maxRedirects: 0 }); const { localComps, localPageFile } = await this.getLocalComponent(proPath, nodeName, pageName); if (!localComps || localComps.length === 0) { let header = JSON.parse(JSON.stringify(axiosRes.headers)); delete header["content-length"]; ctx.set(header); ctx.body = axiosRes.data; return; } let design = []; let wholeComps = []; const url = decodeURIComponent(refUrl); const correctUrl = 'https:' + url.split(':').slice(1).join(':'); const cachePreviewComps = await this.getCachePreviewComps(projectId, correctUrl); if (cachePreviewComps && cachePreviewComps.length > 0) { design = cachePreviewComps.filter((item) => !item.disabled); wholeComps = cachePreviewComps; } else { const reg = /initGlobal\((.*)\)/; const matches = reg.exec(axiosRes.data); let currentComps = []; if (matches) { try { const matchData = JSON.parse(matches[1]); currentComps = (matchData.data && matchData.data.design) ? matchData.data.design : []; } catch (err) { currentComps = []; } } design = [].concat(currentComps, localComps); wholeComps = design; } await axios_1.default({ method: "post", url: "http://localhost:31240/api/h5-extension/previewComps/broadcast", data: { projectId, workbenchId, previewComps: wholeComps, } }); const result = { code: 0, data: { diyScript: `/${localPageFile}?js=mock&proPath=${proPath}&file=${localPageFile}`, design, diyConfig: { type: "youzanyun", version: "2.0" } }, msg: "ok" }; const resData = `/**/ typeof initGlobal === 'function' && initGlobal(${JSON.stringify(result)})`; let header = JSON.parse(JSON.stringify(axiosRes.headers)); delete header["content-length"]; ctx.body = resData; return; } async pageModify(ctx, next) { const { mall_cloud: pageName, nodeName, proPath, projectId, workbenchId } = ctx.query; const url = ctx.href; const { localComps, localPageFile } = await this.getLocalComponent(proPath, nodeName, pageName); let requestHeader = JSON.parse(JSON.stringify(ctx.headers)); requestHeader['accept-encoding'] = 'gzip, deflate'; let axiosRes = await axios_1.default.request({ method: ctx.method, url: ctx.href, headers: requestHeader, data: ctx.isJsonHeader ? ctx.request.body : ctx.req, responseType: "text", validateStatus: function (status) { return true; }, maxRedirects: 0 }); if ((axiosRes.status < 200 || axiosRes.status >= 300) || (!localComps || localComps.length === 0) || (pageName === 'goods-detail__v2' && ctx.path !== '/html/h5-comp-preview')) { await axios_1.default({ method: "post", url: "http://localhost:31240/api/h5-extension/previewComps/broadcast", data: { projectId, workbenchId, previewComps: [] } }); ctx.status = axiosRes.status; let header = JSON.parse(JSON.stringify(axiosRes.headers)); delete header["content-length"]; ctx.set(header); ctx.body = axiosRes.data; return; } let design = ""; const previewComps = await this.getCachePreviewComps(projectId, url); let wholeComps = null; if (previewComps && previewComps.length > 0) { const filteredComps = previewComps.filter((item) => !item.disabled); design = `window._global.design = ${JSON.stringify(filteredComps)};`; wholeComps = JSON.stringify(previewComps); } else { design = ` var design = window._global.design || []; if (design.length == 0 || design[0].type != 'config') { design.unshift({ type: 'config', script: { url: '/${localPageFile}?js=mock&proPath=${proPath}&file=${localPageFile}' } }); } window._global.design = design.concat(${JSON.stringify(localComps)}); `; wholeComps = `window._global.design || []`; } let mallCloudJsRepalce = ` <script src="/${localPageFile}?js=mock&proPath=${proPath}&file=${localPageFile}"></script> `; let designUpdate = ` <script id="customScript"> if (!window._global) { window._global = { design: []}; } ${design} if (window._global.design) { // 去重 var names = window._global.design.map(item => item && (item.type || item.name)); for (var i = 0; i < names.length; i++) { if (names.slice(i + 1).indexOf(names[i]) !== -1) { window._global.design.splice(i, 1); names.splice(i, 1); i--; } } } var xhr = new XMLHttpRequest(); var url = '/preview?type=savePreview'; xhr.open('POST', url, true); var params = { projectId: ${projectId}, workbenchId: ${workbenchId}, previewComps: ${wholeComps} } xhr.setRequestHeader('Content-Type', 'application/json'); xhr.send(JSON.stringify(params)); xhr.onreadystatechange = function () { } </script> `; const content = axiosRes.data; let newContentWithMallCloud = axiosRes.data; if (mallCloudJsRepalce) { const mallCloudJsReg = /<script src="https:\/\/file.yzcdn.cn\/mall-cloud\/\S*?"><\/script>/g; let mallCloudJsIndex = -1; let mallCloudJsMatches; let matchMallCloudJsStr = ''; while ((mallCloudJsMatches = mallCloudJsReg.exec(content)) !== null) { mallCloudJsIndex = mallCloudJsMatches.index; matchMallCloudJsStr = mallCloudJsMatches[0]; } const matchStrLength = matchMallCloudJsStr.length; newContentWithMallCloud = content.substring(0, mallCloudJsIndex) + mallCloudJsRepalce + content.substring(mallCloudJsIndex + matchStrLength); } const wscJsReg = /<script src="\S*?" charset="utf-8" onerror="_cdnFallback\(this\)[\s\S]*?><\/script>/g; let wscJsIndex = -1; let wscMatches; while ((wscMatches = wscJsReg.exec(newContentWithMallCloud)) !== null) { wscJsIndex = wscMatches.index; } const finalContent = newContentWithMallCloud.substring(0, wscJsIndex) + designUpdate + newContentWithMallCloud.substring(wscJsIndex); let header = JSON.parse(JSON.stringify(axiosRes.headers)); delete header["content-length"]; ctx.set(header); ctx.body = finalContent; } }; ActionHtmlModifyService = tslib_1.__decorate([ spring4js_nodejs_1.Service() ], ActionHtmlModifyService); exports.default = ActionHtmlModifyService;