youzanyun-devtool-worker
Version:
- web - ws - proxy
297 lines (296 loc) • 12.2 kB
JavaScript
;
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;