Initial commit
This commit is contained in:
155
mcp-server/utils/remoteParser.js
Normal file
155
mcp-server/utils/remoteParser.js
Normal file
@@ -0,0 +1,155 @@
|
||||
import { JSDOM } from 'jsdom';
|
||||
import axios from 'axios';
|
||||
import vm from 'vm';
|
||||
|
||||
// Cache para los scripts y appParser
|
||||
let appParserCache = null;
|
||||
let windowCache = null;
|
||||
let scriptsCache = null;
|
||||
|
||||
/**
|
||||
* Descarga y ejecuta los scripts remotos necesarios para appParser
|
||||
* Igual que en el frontend (src/main.js)
|
||||
*/
|
||||
async function loadRemoteParser() {
|
||||
if (appParserCache) {
|
||||
return { appParser: appParserCache, window: windowCache };
|
||||
}
|
||||
|
||||
const scripts = [
|
||||
"https://cms.cocosolution.com/lib/plugins/builder_saas/js/lexer.js",
|
||||
"https://cms.cocosolution.com/lib/plugins/builder_saas/js/mixins/vuecomponents.js",
|
||||
"https://cms.cocosolution.com/lib/plugins/builder_saas/js/mixins/builderdata.js",
|
||||
"https://cms.cocosolution.com/lib/plugins/builder_saas/js/mixins/filters.js",
|
||||
"https://cms.cocosolution.com/lib/plugins/builder_saas/js/parseDocument.js",
|
||||
];
|
||||
|
||||
// Crear un contexto jsdom
|
||||
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
|
||||
runScripts: "dangerously",
|
||||
resources: "usable"
|
||||
});
|
||||
|
||||
const window = dom.window;
|
||||
const document = window.document;
|
||||
|
||||
// Mock de objetos necesarios que pueden no estar en jsdom
|
||||
if (!window.btoa) {
|
||||
window.btoa = (str) => Buffer.from(str).toString('base64');
|
||||
}
|
||||
if (!window.atob) {
|
||||
window.atob = (str) => Buffer.from(str, 'base64').toString();
|
||||
}
|
||||
|
||||
// Asegurar que DOMParser esté disponible (jsdom lo tiene en window)
|
||||
// Pero también lo necesitamos como variable global para los scripts
|
||||
const DOMParser = window.DOMParser;
|
||||
|
||||
// Mock de window.bus (puede que no sea necesario para el parseo)
|
||||
if (!window.bus) {
|
||||
window.bus = {
|
||||
$emit: () => {},
|
||||
$on: () => {},
|
||||
$off: () => {}
|
||||
};
|
||||
}
|
||||
|
||||
// Crear contexto VM con todas las referencias necesarias
|
||||
// Los scripts remotos esperan que window, document, DOMParser, etc. estén disponibles globalmente
|
||||
const context = vm.createContext({
|
||||
window: window,
|
||||
document: document,
|
||||
DOMParser: DOMParser, // Añadir DOMParser como variable global
|
||||
console: console,
|
||||
Buffer: Buffer,
|
||||
setTimeout: setTimeout,
|
||||
setInterval: setInterval,
|
||||
clearTimeout: clearTimeout,
|
||||
clearInterval: clearInterval,
|
||||
// Añadir todas las propiedades globales necesarias
|
||||
...global,
|
||||
// Asegurar que las referencias estén disponibles también como variables globales
|
||||
global: global,
|
||||
process: process
|
||||
});
|
||||
|
||||
// Descargar y ejecutar cada script
|
||||
for (const scriptUrl of scripts) {
|
||||
try {
|
||||
console.log(`Descargando script: ${scriptUrl}`);
|
||||
const response = await axios.get(scriptUrl, {
|
||||
timeout: 10000 // 10 segundos de timeout
|
||||
});
|
||||
const scriptContent = response.data;
|
||||
|
||||
// Ejecutar el script en el contexto VM
|
||||
// Los scripts pueden usar 'window', 'document', etc. directamente
|
||||
vm.runInContext(scriptContent, context);
|
||||
} catch (error) {
|
||||
console.error(`Error cargando script ${scriptUrl}:`, error.message);
|
||||
// Si falla un script crítico, lanzar error
|
||||
if (scriptUrl.includes('parseDocument.js')) {
|
||||
throw new Error(`Error crítico cargando parseDocument.js: ${error.message}`);
|
||||
}
|
||||
// Continuar con los demás scripts para los no críticos
|
||||
}
|
||||
}
|
||||
|
||||
// Verificar que appParser esté disponible
|
||||
if (!window.appParser) {
|
||||
throw new Error('appParser no se cargó correctamente desde los scripts remotos');
|
||||
}
|
||||
|
||||
appParserCache = window.appParser;
|
||||
windowCache = window;
|
||||
scriptsCache = scripts;
|
||||
|
||||
return { appParser: appParserCache, window: windowCache };
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene appParser, cargándolo si es necesario
|
||||
*/
|
||||
export async function getAppParser() {
|
||||
const { appParser } = await loadRemoteParser();
|
||||
return appParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper para parseComponents usando appParser remoto
|
||||
* Usa tipo 2 (Twig) explícitamente
|
||||
* Firma real: parseComponents(code, prefixVar, type = 0)
|
||||
*/
|
||||
export async function parseComponents(html, moduleIds = [], listTables = [], prefixVar = "", skipBuilderData = false) {
|
||||
const { appParser, window } = await loadRemoteParser();
|
||||
|
||||
// Setear las variables globales en el window real donde se cargó appParser
|
||||
window.allModules = moduleIds;
|
||||
window.tables = listTables;
|
||||
|
||||
// La firma real es: parseComponents(code, prefixVar, type = 0)
|
||||
// Pasamos 2 (número) para Twig explícitamente
|
||||
return appParser.parseComponents(html, prefixVar, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper para generateBuilderVars usando appParser remoto
|
||||
* Usa tipo 2 (Twig) explícitamente, igual que en Api.js
|
||||
* Nota: El código remoto falla si previousSchema es null, así que pasamos {} en su lugar
|
||||
*/
|
||||
export async function generateBuilderVars(code, previousSchema = null) {
|
||||
const appParser = await getAppParser();
|
||||
// Pasar 2 para Twig (igual que en Api.js: parseInt(type) donde type="2")
|
||||
// El código remoto falla si previousSchema es null, así que usamos {} en su lugar
|
||||
const safePreviousSchema = previousSchema || {};
|
||||
return appParser.generateBuilderVars(code, 2, safePreviousSchema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limpia la caché (útil para forzar recarga)
|
||||
*/
|
||||
export function clearCache() {
|
||||
appParserCache = null;
|
||||
scriptsCache = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user