versacompiler 2.0.8 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/compiler/compile.js +2520 -26
  3. package/dist/compiler/error-reporter.js +467 -38
  4. package/dist/compiler/linter.js +72 -1
  5. package/dist/compiler/minify.js +272 -1
  6. package/dist/compiler/minifyTemplate.js +230 -0
  7. package/dist/compiler/module-resolution-optimizer.js +844 -1
  8. package/dist/compiler/parser.js +336 -1
  9. package/dist/compiler/performance-monitor.js +204 -56
  10. package/dist/compiler/tailwindcss.js +39 -1
  11. package/dist/compiler/transform-optimizer.js +392 -1
  12. package/dist/compiler/transformTStoJS.js +16 -1
  13. package/dist/compiler/transforms.js +554 -1
  14. package/dist/compiler/typescript-compiler.js +172 -2
  15. package/dist/compiler/typescript-error-parser.js +281 -10
  16. package/dist/compiler/typescript-manager.js +304 -2
  17. package/dist/compiler/typescript-sync-validator.js +295 -31
  18. package/dist/compiler/typescript-worker-pool.js +936 -1
  19. package/dist/compiler/typescript-worker-thread.cjs +466 -41
  20. package/dist/compiler/typescript-worker.js +339 -1
  21. package/dist/compiler/vuejs.js +396 -37
  22. package/dist/hrm/VueHRM.js +359 -1
  23. package/dist/hrm/errorScreen.js +83 -1
  24. package/dist/hrm/getInstanciaVue.js +313 -1
  25. package/dist/hrm/initHRM.js +586 -1
  26. package/dist/main.js +353 -7
  27. package/dist/servicios/browserSync.js +587 -5
  28. package/dist/servicios/file-watcher.js +425 -4
  29. package/dist/servicios/logger.js +63 -3
  30. package/dist/servicios/readConfig.js +399 -105
  31. package/dist/utils/excluded-modules.js +37 -1
  32. package/dist/utils/module-resolver.js +466 -1
  33. package/dist/utils/promptUser.js +48 -2
  34. package/dist/utils/proxyValidator.js +68 -1
  35. package/dist/utils/resolve-bin.js +58 -1
  36. package/dist/utils/utils.js +21 -1
  37. package/dist/utils/vue-types-setup.js +435 -241
  38. package/dist/wrappers/eslint-node.js +147 -1
  39. package/dist/wrappers/oxlint-node.js +122 -1
  40. package/dist/wrappers/tailwind-node.js +94 -1
  41. package/package.json +39 -42
@@ -1 +1,359 @@
1
- import{obtenerInstanciaVue as e}from"./getInstanciaVue.js";function t(e,t){let n=[];function r(e){e.name===t&&n.push(e);for(let t of e.children)r(t)}return r(e),n}function n(e){let t=[];for(;e;)t.push(e),e=e.parent;return t}function r(e,t){if(!(!e||typeof e!=`object`))if(e?.type.name===`Suspense`){let n=e?.suspense.activeBranch,i={name:e?.type.name,instancia:n,children:[],parent:t,isRoot:!1};t.children.push(i),r(n,i)}else if(e.component){let n=e.component,r=`Anonymous`;if(n.type){if(n.type.name)r=n.type.name;else if(n.type.__name)r=n.type.__name;else if(typeof n.type==`function`){let e=n.type.name;e&&e!==`Anonymous function`&&(r=e);let t=n.type.toString();t.includes(`BaseTransition`)?r=`Transition`:t.includes(`KeepAlive`)?r=`KeepAlive`:t.includes(`Suspense`)&&(r=`Suspense`)}}let a={name:r,instancia:n,children:[],parent:t,isRoot:!1};t.children.push(a),i(n,a)}else{let n=e.children||e.dynamicChildren;Array.isArray(n)&&n.forEach(e=>{r(e,t)})}}function i(e,t){let n=e.subTree;n&&r(n,t)}export const buildComponentTree=e=>{if(!e||!e.type)return console.warn(`No se pudo construir el árbol de componentes: instancia inválida`),null;let t={name:e.type?.name||e.type?.__name||`Anonymous`,instancia:e,children:[],parent:null,isRoot:!0,from:`root`};return i(e,t),t};function o(e){return e?e.proxy&&typeof e.proxy.$forceUpdate==`function`?(e.proxy.$forceUpdate(),typeof e.update==`function`&&e.update(),e.ctx?._.setupState?.versaComponentKey!==void 0&&e.ctx._.setupState.versaComponentKey++,!0):typeof e.update==`function`?(e.ctx?._.setupState?.versaComponentKey!==void 0&&e.ctx._.setupState.versaComponentKey++,e.update(),!0):!1:!1}function s(e,t,n,r){if(!e||!t||!n||!r)return console.error(`❌ Parámetros inválidos para tryUpdateComponentPath`),!1;for(let r=1;r<e.length;r++){let i=e[r];if(i.isRoot||i.name===`KeepAlive`)return window.location.reload(),!0;if(!i||!i.instancia){console.error(`❌ Nodo padre no válido en el camino:`,i);continue}let a=i.instancia?.type?.components||i.instancia?.components;if(a&&a[n])return a[n]=t,o(i.instancia)||o(i.instancia.proxy)}return!1}export async function reloadComponent(r,i){try{let{normalizedPath:o,nameFile:c}=i;if(!r||!r._instance){let t=await e();if(!t)return console.error(`❌ No se pudo obtener la instancia de Vue`),!1;r=t}if(!o)return console.error(`❌ No se proporcionó relativePath`),!1;let l=window.location.href,u=new URL(l),d=`${u.origin}/${o}`,f=Date.now(),p=`${d}?t=${f}`,m=await import(p);if(!m.default)return console.error(`❌ El módulo importado no tiene export default`),!1;let h=buildComponentTree(r._instance);if(!h)return console.error(`❌ No se pudo construir el árbol de componentes`),!1;let g=t(h,c);if(!g)return console.warn(`⚠️ No se encontró el nodo objetivo para:`,c),!1;console.log(`🔍 Se encontraron ${g.length} instancias del componente ${c}`);let _=0;for(let e=0;e<g.length;e++){let t=g[e];if(t){let i=n(t),a=await s(i,m.default,c,r);a?_++:console.error(`❌ No se pudo actualizar la instancia ${e+1}`)}}let v=_>0;return console.log(`\n📊 Resultado final: ${_}/${g.length} instancias actualizadas`),v}catch(e){return console.error(`❌ Error en reloadComponent:`,e),!1}}
1
+ /**
2
+ * @typedef {Object} TreeNode
3
+ * @property {string} name - Nombre del componente
4
+ * @property {Object} instancia - Instancia del componente Vue
5
+ * @property {TreeNode[]} children - Nodos hijos
6
+ * @property {TreeNode|null} parent - Nodo padre
7
+ * @property {boolean} isRoot - Si es el nodo raíz
8
+ * @property {string} [from] - Origen del nodo
9
+ */
10
+
11
+ import { obtenerInstanciaVue } from './getInstanciaVue.js';
12
+
13
+ /**
14
+ * @typedef {Object} VNode
15
+ * @property {Object} [type] - Tipo del VNode
16
+ * @property {Object} [component] - Componente asociado
17
+ * @property {VNode[]} [children] - VNodes hijos
18
+ * @property {VNode[]} [dynamicChildren] - VNodes dinámicos
19
+ * @property {Object} [suspense] - Objeto suspense
20
+ */
21
+
22
+ /**
23
+ * @typedef {Object} ComponentInstance
24
+ * @property {Object} type - Tipo del componente
25
+ * @property {string} [type.name] - Nombre del tipo
26
+ * @property {string} [type.__name] - Nombre alternativo del tipo
27
+ * @property {Object} [components] - Componentes registrados
28
+ * @property {VNode} subTree - Subárbol del componente
29
+ * @property {Object} [proxy] - Proxy del componente
30
+ * @property {Function} [proxy.$forceUpdate] - Función de actualización forzada
31
+ * @property {Function} [update] - Función de actualización
32
+ * @property {Object} [ctx] - Contexto del componente
33
+ * @property {Object} [ctx._] - Contexto interno del componente
34
+ * @property {Object} [ctx._.setupState] - Estado del setup del componente
35
+ * @property {number} [ctx._.setupState.versaComponentKey] - Clave del componente para HMR
36
+ */
37
+
38
+ /**
39
+ * @typedef {Object} ComponentInfo
40
+ * @property {string} normalizedPath - Ruta normalizada del componente
41
+ * @property {string} nameFile - Nombre del archivo del componente
42
+ */
43
+
44
+ /**
45
+ * @typedef {Object} VueApp
46
+ * @property {ComponentInstance} _instance - Instancia principal de la aplicación
47
+ */
48
+
49
+ /**
50
+ * Busca nodos en el árbol por nombre de instancia
51
+ * @param {TreeNode} tree - Árbol de componentes
52
+ * @param {string} instance - Nombre de la instancia a buscar
53
+ * @returns {TreeNode[]} Array de nodos encontrados
54
+ */
55
+ function findNodeByInstance(tree, instance) {
56
+ const matches = [];
57
+ /**
58
+ * @param {TreeNode} node - Nodo a buscar recursivamente
59
+ */
60
+ function searchRecursively(node) {
61
+ if (node.name === instance) {
62
+ matches.push(node);
63
+ }
64
+ for (const child of node.children) {
65
+ searchRecursively(child);
66
+ }
67
+ }
68
+
69
+ searchRecursively(tree);
70
+ return matches;
71
+ }
72
+ /**
73
+ * Obtiene el camino desde un nodo hasta la raíz
74
+ * @param {TreeNode} node - Nodo inicial
75
+ * @returns {TreeNode[]} Camino desde el nodo hasta la raíz
76
+ */
77
+ function getPathToRoot(node) {
78
+ const path = [];
79
+ while (node) {
80
+ path.push(node);
81
+ node = node.parent;
82
+ }
83
+ return path; // Ordenado desde hijo hasta raíz
84
+ }
85
+
86
+ /**
87
+ * Encuentra componentes recursivamente dentro de un VNode
88
+ * @param {VNode} vnode - VNode a explorar
89
+ * @param {TreeNode} parentTreeNode - Nodo padre en el árbol
90
+ */
91
+ function recursivelyFindComponentsInVNode(vnode, parentTreeNode) {
92
+ if (!vnode || typeof vnode !== 'object') {
93
+ return;
94
+ }
95
+ if (vnode?.type.name === 'Suspense') {
96
+ const childComponentInstance = vnode?.suspense.activeBranch;
97
+ const childTreeNode = {
98
+ name: vnode?.type.name,
99
+ instancia: childComponentInstance,
100
+ children: [],
101
+ parent: parentTreeNode,
102
+ isRoot: false,
103
+ };
104
+ parentTreeNode.children.push(childTreeNode);
105
+ recursivelyFindComponentsInVNode(childComponentInstance, childTreeNode);
106
+ } else if (vnode.component) {
107
+ const childComponentInstance = vnode.component;
108
+
109
+ let componentName = 'Anonymous';
110
+ if (childComponentInstance.type) {
111
+ if (childComponentInstance.type.name) {
112
+ componentName = childComponentInstance.type.name;
113
+ } else if (childComponentInstance.type.__name) {
114
+ componentName = childComponentInstance.type.__name;
115
+ } else if (typeof childComponentInstance.type === 'function') {
116
+ const funcName = childComponentInstance.type.name;
117
+ if (funcName && funcName !== 'Anonymous function') {
118
+ componentName = funcName;
119
+ }
120
+ // Heurísticas para componentes comunes de Vue
121
+ const typeStr = childComponentInstance.type.toString();
122
+ if (typeStr.includes('BaseTransition')) {
123
+ componentName = 'Transition';
124
+ } else if (typeStr.includes('KeepAlive')) {
125
+ componentName = 'KeepAlive';
126
+ } else if (typeStr.includes('Suspense')) {
127
+ componentName = 'Suspense';
128
+ }
129
+ }
130
+ }
131
+
132
+ const childTreeNode = {
133
+ name: componentName,
134
+ instancia: childComponentInstance,
135
+ children: [],
136
+ parent: parentTreeNode,
137
+ isRoot: false,
138
+ };
139
+ parentTreeNode.children.push(childTreeNode);
140
+ traverseComponentInstance(childComponentInstance, childTreeNode);
141
+ } else {
142
+ const childrenToExplore = vnode.children || vnode.dynamicChildren;
143
+ if (Array.isArray(childrenToExplore)) {
144
+ childrenToExplore.forEach(childVNode => {
145
+ recursivelyFindComponentsInVNode(childVNode, parentTreeNode);
146
+ });
147
+ }
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Recorre una instancia de componente y construye el árbol
153
+ * @param {ComponentInstance} componentInstance - Instancia del componente
154
+ * @param {TreeNode} currentTreeNode - Nodo actual del árbol
155
+ */
156
+ function traverseComponentInstance(componentInstance, currentTreeNode) {
157
+ const subTreeVNode = componentInstance.subTree;
158
+
159
+ if (!subTreeVNode) {
160
+ return;
161
+ }
162
+
163
+ recursivelyFindComponentsInVNode(subTreeVNode, currentTreeNode);
164
+ }
165
+
166
+ /**
167
+ * Construye el árbol de componentes desde una instancia raíz
168
+ * @param {ComponentInstance} componentRootInstance - Instancia raíz del componente
169
+ * @returns {TreeNode|null} Árbol de componentes o null si falla
170
+ */
171
+ export const buildComponentTree = componentRootInstance => {
172
+ if (!componentRootInstance || !componentRootInstance.type) {
173
+ console.warn(
174
+ 'No se pudo construir el árbol de componentes: instancia inválida',
175
+ );
176
+ return null;
177
+ }
178
+ const tree = {
179
+ name:
180
+ componentRootInstance.type?.name ||
181
+ componentRootInstance.type?.__name ||
182
+ 'Anonymous',
183
+ instancia: componentRootInstance,
184
+ children: [],
185
+ parent: null,
186
+ isRoot: true,
187
+ from: 'root',
188
+ };
189
+ traverseComponentInstance(componentRootInstance, tree);
190
+
191
+ return tree;
192
+ };
193
+
194
+ /**
195
+ * Intenta forzar la actualización de una instancia de componente
196
+ * @param {ComponentInstance} instance - Instancia del componente a actualizar
197
+ * @returns {boolean} True si la actualización fue exitosa, false en caso contrario
198
+ */
199
+ function tryForceUpdate(instance) {
200
+ if (!instance) {
201
+ return false;
202
+ }
203
+ if (instance.proxy && typeof instance.proxy.$forceUpdate === 'function') {
204
+ instance.proxy.$forceUpdate();
205
+ if (typeof instance.update === 'function') {
206
+ instance.update();
207
+ }
208
+ // buscar una variable en el componente que se llame versaComponentKey y sumarle 1
209
+ if (instance.ctx?._.setupState?.versaComponentKey !== undefined) {
210
+ instance.ctx._.setupState.versaComponentKey++;
211
+ }
212
+ return true;
213
+ }
214
+ if (typeof instance.update === 'function') {
215
+ if (instance.ctx?._.setupState?.versaComponentKey !== undefined) {
216
+ instance.ctx._.setupState.versaComponentKey++;
217
+ }
218
+ instance.update();
219
+ return true;
220
+ }
221
+ return false;
222
+ }
223
+
224
+ /**
225
+ * Intenta actualizar un componente en el camino del árbol
226
+ * @param {TreeNode[]} path - Camino de nodos desde el componente hasta la raíz
227
+ * @param {Object} newComponent - Nuevo componente a usar
228
+ * @param {string} componentName - Nombre del componente
229
+ * @param {VueApp} App - Aplicación Vue
230
+ * @returns {boolean} True si la actualización fue exitosa
231
+ */
232
+ function tryUpdateComponentPath(path, newComponent, componentName, App) {
233
+ if (!path || !newComponent || !componentName || !App) {
234
+ console.error('❌ Parámetros inválidos para tryUpdateComponentPath');
235
+ return false;
236
+ }
237
+
238
+ // Recorrer el path desde el padre hacia la raíz (saltando el primer elemento que es el propio componente)
239
+ for (let i = 1; i < path.length; i++) {
240
+ const parent = path[i];
241
+
242
+ if (parent.isRoot || parent.name === 'KeepAlive') {
243
+ window.location.reload();
244
+ return true;
245
+ }
246
+
247
+ if (!parent || !parent.instancia) {
248
+ console.error('❌ Nodo padre no válido en el camino:', parent);
249
+ continue; // Continúa con el siguiente padre en lugar de fallar
250
+ }
251
+
252
+ // Actualizar la instancia del componente
253
+ const componentsDefinition =
254
+ parent.instancia?.type?.components || parent.instancia?.components;
255
+
256
+ if (componentsDefinition && componentsDefinition[componentName]) {
257
+ componentsDefinition[componentName] = newComponent;
258
+
259
+ // Forzar actualización de la instancia padre
260
+ return (
261
+ tryForceUpdate(parent.instancia) ||
262
+ tryForceUpdate(parent.instancia.proxy)
263
+ );
264
+ }
265
+ }
266
+
267
+ return false;
268
+ }
269
+
270
+ /**
271
+ * Recarga un componente Vue con Hot Module Replacement
272
+ * @param {VueApp} App - Aplicación Vue principal
273
+ * @param {ComponentInfo} Component - Información del componente a recargar
274
+ * @returns {Promise<boolean>} Promise que resuelve a true si la recarga fue exitosa
275
+ */
276
+ export async function reloadComponent(App, Component) {
277
+ try {
278
+ const { normalizedPath: relativePath, nameFile: componentName } =
279
+ Component;
280
+ if (!App || !App._instance) {
281
+ const vueInstance = await obtenerInstanciaVue();
282
+ if (!vueInstance) {
283
+ console.error('❌ No se pudo obtener la instancia de Vue');
284
+ return false;
285
+ }
286
+ App = vueInstance;
287
+ }
288
+
289
+ if (!relativePath) {
290
+ console.error('❌ No se proporcionó relativePath');
291
+ return false;
292
+ }
293
+
294
+ const baseUrl = window.location.href;
295
+ const newBaseUrl = new URL(baseUrl);
296
+ const urlOrigin = `${newBaseUrl.origin}/${relativePath}`;
297
+ const timestamp = Date.now();
298
+ const moduleUrl = `${urlOrigin}?t=${timestamp}`;
299
+
300
+ const module = await import(moduleUrl);
301
+
302
+ if (!module.default) {
303
+ console.error('❌ El módulo importado no tiene export default');
304
+ return false;
305
+ }
306
+
307
+ const componentTree = buildComponentTree(App._instance);
308
+ if (!componentTree) {
309
+ console.error('❌ No se pudo construir el árbol de componentes');
310
+ return false;
311
+ }
312
+
313
+ const targetNodes = findNodeByInstance(componentTree, componentName);
314
+ if (!targetNodes) {
315
+ console.warn(
316
+ '⚠️ No se encontró el nodo objetivo para:',
317
+ componentName,
318
+ );
319
+
320
+ return false;
321
+ }
322
+
323
+ console.log(
324
+ `🔍 Se encontraron ${targetNodes.length} instancias del componente ${componentName}`,
325
+ );
326
+
327
+ let successfulUpdates = 0; // Procesar TODAS las instancias encontradas
328
+ for (let i = 0; i < targetNodes.length; i++) {
329
+ const node = targetNodes[i];
330
+ if (node) {
331
+ const path = getPathToRoot(node);
332
+ const updateResult = await tryUpdateComponentPath(
333
+ path,
334
+ module.default,
335
+ componentName,
336
+ App,
337
+ );
338
+
339
+ if (updateResult) {
340
+ successfulUpdates++;
341
+ } else {
342
+ console.error(
343
+ `❌ No se pudo actualizar la instancia ${i + 1}`,
344
+ );
345
+ }
346
+ }
347
+ }
348
+
349
+ const hasSuccessfulUpdate = successfulUpdates > 0;
350
+ console.log(
351
+ `\n📊 Resultado final: ${successfulUpdates}/${targetNodes.length} instancias actualizadas`,
352
+ );
353
+
354
+ return hasSuccessfulUpdate;
355
+ } catch (error) {
356
+ console.error('❌ Error en reloadComponent:', error);
357
+ return false;
358
+ }
359
+ }
@@ -1 +1,83 @@
1
- let e;export function hideErrorOverlay(){let t=document.getElementById(`versa-hmr-error-overlay`);t&&t.remove(),e=null}export function showErrorOverlay(n,r=``){hideErrorOverlay(),e=document.createElement(`div`),e.id=`versa-hmr-error-overlay`,e.style.position=`fixed`,e.style.top=`0`,e.style.left=`0`,e.style.width=`100vw`,e.style.height=`100vh`,e.style.backgroundColor=`rgba(0, 0, 0, 1.85)`,e.style.color=`#ff8080`,e.style.zIndex=`999999`,e.style.display=`flex`,e.style.flexDirection=`column`,e.style.alignItems=`center`,e.style.justifyContent=`center`,e.style.fontFamily=`monospace`,e.style.fontSize=`16px`,e.style.padding=`20px`,e.style.boxSizing=`border-box`,e.style.textAlign=`left`,e.style.overflow=`auto`;let i=document.createElement(`h2`);i.textContent=`Versa HMR Error`,i.style.color=`#ff4d4d`,i.style.fontSize=`24px`,i.style.marginBottom=`20px`;let a=document.createElement(`div`);a.textContent=n,a.style.marginBottom=`15px`,a.style.whiteSpace=`pre-wrap`;let o=document.createElement(`pre`);o.textContent=r,o.style.backgroundColor=`rgba(255, 255, 255, 0.1)`,o.style.padding=`10px`,o.style.borderRadius=`5px`,o.style.maxHeight=`50vh`,o.style.overflow=`auto`,o.style.width=`100%`,o.style.maxWidth=`800px`,e.appendChild(i),e.appendChild(a),r&&e.appendChild(o),document.body.appendChild(e)}
1
+ /**
2
+ * Variable global que mantiene la referencia al overlay de error actual
3
+ * @type {HTMLElement|null}
4
+ */
5
+ let errorOverlay;
6
+
7
+ /**
8
+ * Oculta y remueve el overlay de error actual del DOM
9
+ * @returns {void}
10
+ */
11
+ export function hideErrorOverlay() {
12
+ const existingOverlay = document.getElementById('versa-hmr-error-overlay');
13
+ if (existingOverlay) {
14
+ existingOverlay.remove();
15
+ }
16
+ errorOverlay = null;
17
+ }
18
+
19
+ /**
20
+ * Muestra un overlay de error personalizado para errores de HMR (Hot Module Replacement).
21
+ * @param {string} errorMessage - Mensaje de error principal.
22
+ * @param {string} [errorDetails=''] - Detalles adicionales del error, opcional.
23
+ * @returns {void}
24
+ */
25
+ export function showErrorOverlay(errorMessage, errorDetails = '') {
26
+ hideErrorOverlay(); // Asegurar que no haya overlays duplicados
27
+
28
+ // Crear el contenedor principal del overlay
29
+ errorOverlay = document.createElement('div');
30
+ errorOverlay.id = 'versa-hmr-error-overlay';
31
+ errorOverlay.style.position = 'fixed';
32
+ errorOverlay.style.top = '0';
33
+ errorOverlay.style.left = '0';
34
+ errorOverlay.style.width = '100vw';
35
+ errorOverlay.style.height = '100vh';
36
+ errorOverlay.style.backgroundColor = 'rgba(0, 0, 0, 1.85)';
37
+ errorOverlay.style.color = '#ff8080';
38
+ errorOverlay.style.zIndex = '999999';
39
+ errorOverlay.style.display = 'flex';
40
+ errorOverlay.style.flexDirection = 'column';
41
+ errorOverlay.style.alignItems = 'center';
42
+ errorOverlay.style.justifyContent = 'center';
43
+ errorOverlay.style.fontFamily = 'monospace';
44
+ errorOverlay.style.fontSize = '16px';
45
+ errorOverlay.style.padding = '20px';
46
+ errorOverlay.style.boxSizing = 'border-box';
47
+ errorOverlay.style.textAlign = 'left';
48
+ errorOverlay.style.overflow = 'auto';
49
+
50
+ // Crear el título del overlay
51
+ const title = document.createElement('h2');
52
+ title.textContent = 'Versa HMR Error';
53
+ title.style.color = '#ff4d4d';
54
+ title.style.fontSize = '24px';
55
+ title.style.marginBottom = '20px';
56
+
57
+ // Crear el contenedor del mensaje principal
58
+ const messageDiv = document.createElement('div');
59
+ messageDiv.textContent = errorMessage;
60
+ messageDiv.style.marginBottom = '15px';
61
+ messageDiv.style.whiteSpace = 'pre-wrap';
62
+
63
+ // Crear el contenedor de detalles del error
64
+ const detailsPre = document.createElement('pre');
65
+ detailsPre.textContent = errorDetails;
66
+ detailsPre.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
67
+ detailsPre.style.padding = '10px';
68
+ detailsPre.style.borderRadius = '5px';
69
+ detailsPre.style.maxHeight = '50vh';
70
+ detailsPre.style.overflow = 'auto';
71
+ detailsPre.style.width = '100%';
72
+ detailsPre.style.maxWidth = '800px';
73
+
74
+ // Agregar elementos al overlay
75
+ errorOverlay.appendChild(title);
76
+ errorOverlay.appendChild(messageDiv);
77
+ if (errorDetails) {
78
+ errorOverlay.appendChild(detailsPre);
79
+ }
80
+
81
+ // Agregar el overlay al DOM
82
+ document.body.appendChild(errorOverlay);
83
+ }