versacompiler 2.5.0 → 2.6.1
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.
- package/README.md +70 -54
- package/dist/compiler/compile-worker-pool.js +12 -0
- package/dist/compiler/compile.js +102 -17
- package/dist/compiler/error-reporter.js +12 -0
- package/dist/compiler/integrity-validator.js +12 -0
- package/dist/compiler/linter.js +12 -0
- package/dist/compiler/minify.js +12 -0
- package/dist/compiler/minifyTemplate.js +12 -0
- package/dist/compiler/module-resolution-optimizer.js +13 -1
- package/dist/compiler/parser.js +12 -0
- package/dist/compiler/performance-monitor.js +12 -0
- package/dist/compiler/pipeline/build-pipeline.js +12 -0
- package/dist/compiler/pipeline/core-plugins.js +12 -0
- package/dist/compiler/pipeline/module-graph.js +12 -0
- package/dist/compiler/pipeline/plugin-driver.js +12 -0
- package/dist/compiler/pipeline/types.js +12 -0
- package/dist/compiler/tailwindcss.js +12 -0
- package/dist/compiler/transform-optimizer.js +12 -0
- package/dist/compiler/transformTStoJS.js +38 -5
- package/dist/compiler/transforms.js +12 -0
- package/dist/compiler/typescript-compiler.js +12 -0
- package/dist/compiler/typescript-error-parser.js +12 -0
- package/dist/compiler/typescript-manager.js +12 -0
- package/dist/compiler/typescript-sync-validator.js +12 -0
- package/dist/compiler/typescript-worker-pool.js +12 -0
- package/dist/compiler/typescript-worker.js +12 -0
- package/dist/compiler/vuejs.js +41 -15
- package/dist/config.js +12 -0
- package/dist/hrm/VueHRM.js +132 -7
- package/dist/hrm/errorScreen.js +12 -0
- package/dist/hrm/getInstanciaVue.js +12 -0
- package/dist/hrm/initHRM.js +117 -9
- package/dist/hrm/versaHMR.js +317 -0
- package/dist/main.js +9 -2
- package/dist/servicios/browserSync.js +119 -4
- package/dist/servicios/file-watcher.js +104 -15
- package/dist/servicios/logger.js +12 -0
- package/dist/servicios/readConfig.js +13 -1
- package/dist/servicios/versacompile.config.types.js +12 -0
- package/dist/utils/excluded-modules.js +12 -0
- package/dist/utils/module-resolver.js +12 -0
- package/dist/utils/promptUser.js +12 -0
- package/dist/utils/proxyValidator.js +12 -0
- package/dist/utils/resolve-bin.js +12 -0
- package/dist/utils/utils.js +12 -0
- package/dist/utils/vue-types-setup.js +14 -2
- package/dist/wrappers/eslint-node.js +12 -0
- package/dist/wrappers/oxlint-node.js +12 -0
- package/dist/wrappers/tailwind-node.js +12 -0
- package/package.json +4 -3
|
@@ -1,16 +1,49 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
import { transform } from '/node_modules/oxc-transform/browser.js';
|
|
2
|
-
export async function
|
|
14
|
+
export async function transpileTStoJS(filePath, sourceCode) {
|
|
3
15
|
try {
|
|
4
16
|
const { code: outputText, declaration, errors: diagnostics, } = await transform(filePath, sourceCode);
|
|
17
|
+
// Si oxc-transform devuelve código vacío ante una entrada no vacía,
|
|
18
|
+
// usar el fuente original como fallback para no corromper el pipeline.
|
|
19
|
+
if (!outputText && sourceCode.trim()) {
|
|
20
|
+
return {
|
|
21
|
+
outputText: sourceCode,
|
|
22
|
+
declaration: declaration || '',
|
|
23
|
+
diagnostics: [
|
|
24
|
+
`Warning: oxc-transform produjo salida vacía para ${filePath}, usando fuente original`,
|
|
25
|
+
...(diagnostics ?? []).map(d => typeof d === 'string' ? d : JSON.stringify(d)),
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
5
29
|
return {
|
|
6
|
-
outputText: outputText,
|
|
30
|
+
outputText: outputText ?? sourceCode,
|
|
7
31
|
declaration: declaration || '',
|
|
8
|
-
diagnostics: diagnostics
|
|
32
|
+
diagnostics: (diagnostics ?? []).map(d => typeof d === 'string' ? d : JSON.stringify(d)),
|
|
9
33
|
};
|
|
10
34
|
}
|
|
11
35
|
catch (error) {
|
|
12
|
-
|
|
13
|
-
|
|
36
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
37
|
+
// Fallback al fuente original para que el pipeline no reciba código vacío
|
|
38
|
+
return {
|
|
39
|
+
outputText: sourceCode,
|
|
40
|
+
declaration: '',
|
|
41
|
+
diagnostics: [
|
|
42
|
+
`Error durante transpilación de ${filePath}: ${errorMsg}. Usando fuente original.`,
|
|
43
|
+
],
|
|
44
|
+
};
|
|
14
45
|
}
|
|
15
46
|
}
|
|
47
|
+
/** @deprecated Usar transpileTStoJS (corrección de typo histórico) */
|
|
48
|
+
export const traspileTStoJS = transpileTStoJS;
|
|
16
49
|
//# sourceMappingURL=transformTStoJS.js.map
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
import path from 'node:path';
|
|
2
14
|
import { env } from 'node:process';
|
|
3
15
|
import { logger } from '../servicios/logger.js';
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
import fs from 'node:fs';
|
|
2
14
|
import path from 'node:path';
|
|
3
15
|
import * as process from 'node:process';
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
import { readFileSync } from 'node:fs';
|
|
2
14
|
import * as typescript from 'typescript';
|
|
3
15
|
/**
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
import fs from 'node:fs';
|
|
2
14
|
import path from 'node:path';
|
|
3
15
|
import * as process from 'node:process';
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* TypeScript Sync Validator - Validación síncrona de tipos como fallback
|
|
3
15
|
* Contiene la lógica extraída del módulo principal para cuando el worker no está disponible
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* TypeScript Worker Pool - Pool de workers para compilación paralela
|
|
3
15
|
* Reemplaza el worker único con múltiples workers para aprovecha la concurrencia real
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* TypeScript Worker Manager - Gestiona workers dedicados para type checking asíncrono
|
|
3
15
|
* Implementa el patrón Singleton para reutilizar workers entre compilaciones
|
package/dist/compiler/vuejs.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
import { createHash } from 'node:crypto';
|
|
2
14
|
import path from 'node:path';
|
|
3
15
|
import * as vCompiler from 'vue/compiler-sfc';
|
|
@@ -63,19 +75,30 @@ class VueHMRInjectionCache {
|
|
|
63
75
|
else {
|
|
64
76
|
injectedData = originalData.replace(/(<script.*?>)/, `$1${varContent}`);
|
|
65
77
|
}
|
|
66
|
-
// Inyectar :key en el template
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
// Inyectar :key en el primer elemento hijo del template.
|
|
79
|
+
// Dos pasos para evitar backtracking catastrófico (ReDoS) que ocurría con
|
|
80
|
+
// el pattern combinado /(<template[^>]*>[\s\S]*?)(<(\w+)([^>]*?))(\/?>)/
|
|
81
|
+
const templateTagMatch = /(<template[^>]*>)/.exec(injectedData);
|
|
82
|
+
if (templateTagMatch) {
|
|
83
|
+
const templateEnd = templateTagMatch.index + templateTagMatch[0].length;
|
|
84
|
+
const afterTemplate = injectedData.slice(templateEnd);
|
|
85
|
+
// Buscar el primer tag de elemento (ignora espacios/comentarios) justo después del <template>
|
|
86
|
+
const firstChildMatch = /^(\s*)(<(\w+)([^>]*?)(\/?>))/.exec(afterTemplate);
|
|
87
|
+
if (firstChildMatch) {
|
|
88
|
+
const [, whitespace = '', fullTag = '', tagName, attrs = '', closing,] = firstChildMatch;
|
|
89
|
+
if (!attrs.includes(':key=') && !attrs.includes('key=')) {
|
|
90
|
+
const isSelfClosing = closing === '/>';
|
|
91
|
+
const newTag = isSelfClosing
|
|
92
|
+
? `<${tagName}${attrs} :key="versaComponentKey" />`
|
|
93
|
+
: `<${tagName}${attrs} :key="versaComponentKey">`;
|
|
94
|
+
injectedData =
|
|
95
|
+
injectedData.slice(0, templateEnd) +
|
|
96
|
+
whitespace +
|
|
97
|
+
newTag +
|
|
98
|
+
afterTemplate.slice(whitespace.length + fullTag.length);
|
|
99
|
+
}
|
|
77
100
|
}
|
|
78
|
-
}
|
|
101
|
+
}
|
|
79
102
|
// Cachear resultado
|
|
80
103
|
this.cache.set(cacheKey, {
|
|
81
104
|
contentHash,
|
|
@@ -167,8 +190,6 @@ export const preCompileVue = async (data, source, isProd = false) => {
|
|
|
167
190
|
scriptInfo: undefined,
|
|
168
191
|
};
|
|
169
192
|
}
|
|
170
|
-
// Guardar el código original antes de inyectar HMR
|
|
171
|
-
const originalData = data;
|
|
172
193
|
if (!isProd) {
|
|
173
194
|
const { injectedData } = hmrInjectionCache.getOrGenerateHMRInjection(data, fileName);
|
|
174
195
|
data = injectedData;
|
|
@@ -312,10 +333,14 @@ export const preCompileVue = async (data, source, isProd = false) => {
|
|
|
312
333
|
filename: `${fileName}.vue`,
|
|
313
334
|
});
|
|
314
335
|
});
|
|
336
|
+
// data-versa-hmr-component permite a VueHRM.js eliminar style tags
|
|
337
|
+
// de ciclos HMR anteriores para evitar acumulación de estilos duplicados.
|
|
338
|
+
const sanitizedForAttr = fileName.replace(/[^a-zA-Z0-9_-]/g, '');
|
|
315
339
|
const insertStyles = compiledStyles.length
|
|
316
340
|
? `(function(){
|
|
317
341
|
let styleTag = document.createElement('style');
|
|
318
342
|
styleTag.setAttribute('data-v-${id}', '');
|
|
343
|
+
styleTag.setAttribute('data-versa-hmr-component', '${sanitizedForAttr}');
|
|
319
344
|
styleTag.innerHTML = \`${compiledStyles.map((s) => s.code).join('\n')}\`;
|
|
320
345
|
document.head.appendChild(styleTag);
|
|
321
346
|
})();`
|
|
@@ -380,6 +405,8 @@ export const preCompileVue = async (data, source, isProd = false) => {
|
|
|
380
405
|
export default ${componentName}; `;
|
|
381
406
|
output = `${output}\n${finishComponent}`;
|
|
382
407
|
// 🚀 OPTIMIZACIÓN CRÍTICA: Evitar crear scriptInfo si no hay script
|
|
408
|
+
// originalData NO se incluye en scriptInfo para evitar retener la cadena completa
|
|
409
|
+
// del .vue en memoria. Se pasa por separado como sourceCode en parseTypeScriptErrors.
|
|
383
410
|
const result = {
|
|
384
411
|
lang: finalCompiledScript.lang,
|
|
385
412
|
error: null,
|
|
@@ -391,7 +418,6 @@ export const preCompileVue = async (data, source, isProd = false) => {
|
|
|
391
418
|
startLine: (descriptor.script || descriptor.scriptSetup).loc?.start
|
|
392
419
|
.line || 1,
|
|
393
420
|
content: (descriptor.script || descriptor.scriptSetup).content,
|
|
394
|
-
originalData: originalData, // String directa, no closure
|
|
395
421
|
};
|
|
396
422
|
}
|
|
397
423
|
return result;
|
package/dist/config.js
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
export { defineConfig, } from './servicios/versacompile.config.types';
|
|
2
14
|
//# sourceMappingURL=config.js.map
|
package/dist/hrm/VueHRM.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* @typedef {Object} TreeNode
|
|
3
15
|
* @property {string} name - Nombre del componente
|
|
@@ -222,7 +234,80 @@ function tryForceUpdate(instance) {
|
|
|
222
234
|
}
|
|
223
235
|
|
|
224
236
|
/**
|
|
225
|
-
*
|
|
237
|
+
* Limpia los caches internos de Vue para una definición de componente.
|
|
238
|
+
* Necesario para que Vue detecte el cambio de props/emits/options.
|
|
239
|
+
* @param {Object} appContext - Contexto de la app Vue (instance.appContext)
|
|
240
|
+
* @param {Object} componentDef - Definición del componente
|
|
241
|
+
*/
|
|
242
|
+
function clearVueCaches(appContext, componentDef) {
|
|
243
|
+
if (!appContext || !componentDef) return;
|
|
244
|
+
try {
|
|
245
|
+
appContext.propsCache?.delete(componentDef);
|
|
246
|
+
appContext.emitsCache?.delete(componentDef);
|
|
247
|
+
appContext.optionsCache?.delete(componentDef);
|
|
248
|
+
} catch {
|
|
249
|
+
// Los caches pueden no existir en todas las versiones de Vue
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Actualiza una instancia de componente Vue en-place con la nueva definición.
|
|
255
|
+
* Muta el objeto `instance.type` directamente para que TODAS las referencias
|
|
256
|
+
* a la definición (incluidas las capturadas en closures de render functions
|
|
257
|
+
* de componentes padre que hacen import estático) vean la nueva versión.
|
|
258
|
+
*
|
|
259
|
+
* @param {Object} instance - Instancia Vue del componente a actualizar
|
|
260
|
+
* @param {Object} newComponentDef - Nueva definición del componente
|
|
261
|
+
* @returns {boolean} true si la actualización fue exitosa
|
|
262
|
+
*/
|
|
263
|
+
function updateInstanceInPlace(instance, newComponentDef) {
|
|
264
|
+
if (!instance || !newComponentDef) return false;
|
|
265
|
+
|
|
266
|
+
const oldDef = instance.type;
|
|
267
|
+
if (!oldDef || typeof oldDef !== 'object') return false;
|
|
268
|
+
|
|
269
|
+
// 1. Mutar la definición existente en-place.
|
|
270
|
+
// Object.assign copia propiedades enumerables; copiamos render/setup
|
|
271
|
+
// explícitamente porque pueden no ser enumerables en algunos builds.
|
|
272
|
+
Object.assign(oldDef, newComponentDef);
|
|
273
|
+
if (newComponentDef.render) oldDef.render = newComponentDef.render;
|
|
274
|
+
if (newComponentDef.setup) oldDef.setup = newComponentDef.setup;
|
|
275
|
+
if (newComponentDef.ssrRender) oldDef.ssrRender = newComponentDef.ssrRender;
|
|
276
|
+
|
|
277
|
+
// 2. Actualizar instance.render directamente.
|
|
278
|
+
// Vue almacena la referencia a la render function en instance.render durante
|
|
279
|
+
// el mount (handleSetupResult), y es ESA la que llama en cada patch.
|
|
280
|
+
// Cambiar solo instance.type.render NO es suficiente — hay que actualizar
|
|
281
|
+
// también instance.render para que el próximo update use la nueva template.
|
|
282
|
+
if (newComponentDef.render && typeof instance.render !== 'undefined') {
|
|
283
|
+
instance.render = newComponentDef.render;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// 3. Limpiar caches internos de Vue para que re-evalúe props/emits/options.
|
|
287
|
+
clearVueCaches(instance.appContext, oldDef);
|
|
288
|
+
|
|
289
|
+
// 4. Forzar actualización de ESTA instancia directamente (no solo del padre).
|
|
290
|
+
// Incrementar versaComponentKey para triggear el :key del template.
|
|
291
|
+
if (instance.ctx?._.setupState?.versaComponentKey !== undefined) {
|
|
292
|
+
instance.ctx._.setupState.versaComponentKey++;
|
|
293
|
+
}
|
|
294
|
+
if (typeof instance.update === 'function') {
|
|
295
|
+
instance.update();
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
if (instance.proxy && typeof instance.proxy.$forceUpdate === 'function') {
|
|
299
|
+
instance.proxy.$forceUpdate();
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Intenta actualizar un componente en el camino del árbol.
|
|
308
|
+
* Ahora usa mutación in-place de la definición + limpieza de caches Vue,
|
|
309
|
+
* en lugar de reemplazar la referencia en el mapa de components del padre.
|
|
310
|
+
*
|
|
226
311
|
* @param {TreeNode[]} path - Camino de nodos desde el componente hasta la raíz
|
|
227
312
|
* @param {Object} newComponent - Nuevo componente a usar
|
|
228
313
|
* @param {string} componentName - Nombre del componente
|
|
@@ -235,7 +320,25 @@ function tryUpdateComponentPath(path, newComponent, componentName, App) {
|
|
|
235
320
|
return false;
|
|
236
321
|
}
|
|
237
322
|
|
|
238
|
-
//
|
|
323
|
+
// path[0] es el nodo del propio componente a actualizar.
|
|
324
|
+
// Intentar actualización directa en la instancia del componente.
|
|
325
|
+
const targetNode = path[0];
|
|
326
|
+
if (targetNode?.instancia) {
|
|
327
|
+
const updated = updateInstanceInPlace(
|
|
328
|
+
targetNode.instancia,
|
|
329
|
+
newComponent,
|
|
330
|
+
);
|
|
331
|
+
if (updated) {
|
|
332
|
+
// También forzar actualización del padre para que el vdom se reconcilie.
|
|
333
|
+
const parentNode = path[1];
|
|
334
|
+
if (parentNode?.instancia && !parentNode.isRoot) {
|
|
335
|
+
tryForceUpdate(parentNode.instancia);
|
|
336
|
+
}
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Fallback: recorrer hacia el padre si el nodo propio no es accesible.
|
|
239
342
|
for (let i = 1; i < path.length; i++) {
|
|
240
343
|
const parent = path[i];
|
|
241
344
|
|
|
@@ -244,19 +347,29 @@ function tryUpdateComponentPath(path, newComponent, componentName, App) {
|
|
|
244
347
|
return true;
|
|
245
348
|
}
|
|
246
349
|
|
|
247
|
-
if (!parent
|
|
350
|
+
if (!parent?.instancia) {
|
|
248
351
|
console.error('❌ Nodo padre no válido en el camino:', parent);
|
|
249
|
-
continue;
|
|
352
|
+
continue;
|
|
250
353
|
}
|
|
251
354
|
|
|
252
|
-
// Actualizar la instancia del componente
|
|
253
355
|
const componentsDefinition =
|
|
254
356
|
parent.instancia?.type?.components || parent.instancia?.components;
|
|
255
357
|
|
|
256
358
|
if (componentsDefinition && componentsDefinition[componentName]) {
|
|
257
|
-
|
|
359
|
+
// Mutar la definición existente en el mapa del padre también,
|
|
360
|
+
// para que nuevas instancias del componente creadas después se usen
|
|
361
|
+
// con la definición actualizada.
|
|
362
|
+
const existingDef = componentsDefinition[componentName];
|
|
363
|
+
if (existingDef && typeof existingDef === 'object') {
|
|
364
|
+
Object.assign(existingDef, newComponent);
|
|
365
|
+
if (newComponent.render)
|
|
366
|
+
existingDef.render = newComponent.render;
|
|
367
|
+
if (newComponent.setup) existingDef.setup = newComponent.setup;
|
|
368
|
+
clearVueCaches(parent.instancia.appContext, existingDef);
|
|
369
|
+
} else {
|
|
370
|
+
componentsDefinition[componentName] = newComponent;
|
|
371
|
+
}
|
|
258
372
|
|
|
259
|
-
// Forzar actualización de la instancia padre
|
|
260
373
|
return (
|
|
261
374
|
tryForceUpdate(parent.instancia) ||
|
|
262
375
|
tryForceUpdate(parent.instancia.proxy)
|
|
@@ -297,6 +410,18 @@ export async function reloadComponent(App, Component) {
|
|
|
297
410
|
const timestamp = Date.now();
|
|
298
411
|
const moduleUrl = `${urlOrigin}?t=${timestamp}`;
|
|
299
412
|
|
|
413
|
+
// Eliminar style tags del ciclo HMR anterior para este componente
|
|
414
|
+
// para evitar acumulación de estilos duplicados en el documento.
|
|
415
|
+
const componentName_clean = componentName.replace(
|
|
416
|
+
/[^a-zA-Z0-9_-]/g,
|
|
417
|
+
'',
|
|
418
|
+
);
|
|
419
|
+
document
|
|
420
|
+
.querySelectorAll(
|
|
421
|
+
`[data-versa-hmr-component="${componentName_clean}"]`,
|
|
422
|
+
)
|
|
423
|
+
.forEach(el => el.remove());
|
|
424
|
+
|
|
300
425
|
const module = await import(moduleUrl);
|
|
301
426
|
|
|
302
427
|
if (!module.default) {
|
package/dist/hrm/errorScreen.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* Variable global que mantiene la referencia al overlay de error actual
|
|
3
15
|
* @type {HTMLElement|null}
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* VersaCompiler HMR shim [dev] */
|
|
2
|
+
if (typeof window !== 'undefined' && window.__versaHMR) {
|
|
3
|
+
(() => {
|
|
4
|
+
const _id = new URL(import.meta.url).pathname;
|
|
5
|
+
import.meta.hot = {
|
|
6
|
+
accept(cb) { window.__versaHMR.accept(_id, typeof cb === 'function' ? cb : () => {}); },
|
|
7
|
+
invalidate() { window.__versaHMR._invalidate?.(_id); },
|
|
8
|
+
dispose(cb) { window.__versaHMR._onDispose?.(_id, cb); },
|
|
9
|
+
get data() { return window.__versaHMR._getHotData?.(_id) ?? {}; },
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* Script para obtener la instancia de Vue usando solo JavaScript
|
|
3
15
|
* Compatible con Vue 2 y Vue 3
|