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
package/dist/hrm/initHRM.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
|
* @fileoverview Inicialización del sistema Hot Module Replacement (HMR) para VersaCompiler
|
|
3
15
|
* Este archivo maneja la conexión con BrowserSync y configura los listeners para HMR de Vue
|
|
@@ -11,6 +23,9 @@
|
|
|
11
23
|
|
|
12
24
|
import { hideErrorOverlay, showErrorOverlay } from './errorScreen.js';
|
|
13
25
|
import { obtenerInstanciaVue } from './getInstanciaVue.js';
|
|
26
|
+
|
|
27
|
+
// oxlint-disable-next-line import/no-unassigned-import -- side-effect: inicializa window.__versaHMR
|
|
28
|
+
import './versaHMR.js';
|
|
14
29
|
import { reloadComponent } from './VueHRM.js';
|
|
15
30
|
|
|
16
31
|
/**
|
|
@@ -343,6 +358,27 @@ async function initSocket(retries = 0) {
|
|
|
343
358
|
socket.on('reloadFull', () => window.location.reload()); // Obtener la instancia de Vue con toda la lógica integrada
|
|
344
359
|
let vueInstance = await obtenerInstanciaVue();
|
|
345
360
|
|
|
361
|
+
// Exponer función de recarga Vue por path para que los shims de módulos
|
|
362
|
+
// puedan disparar una actualización de instancia Vue cuando una dependencia
|
|
363
|
+
// (sampleFile.js, etc.) se actualiza vía HMR propagation.
|
|
364
|
+
if (window.__versaHMR) {
|
|
365
|
+
window.__versaHMR._reloadVueByPath = async path => {
|
|
366
|
+
try {
|
|
367
|
+
vueInstance = window.__VUE_APP__ || vueInstance;
|
|
368
|
+
// normalizedPath sin slash inicial (reloadComponent usa origin + '/' + path)
|
|
369
|
+
const normalizedPath = path.replace(/^\//, '');
|
|
370
|
+
const nameFile =
|
|
371
|
+
path.split('/').pop()?.replace('.js', '') ?? '';
|
|
372
|
+
await reloadComponent(vueInstance, {
|
|
373
|
+
normalizedPath,
|
|
374
|
+
nameFile,
|
|
375
|
+
});
|
|
376
|
+
} catch (err) {
|
|
377
|
+
console.error('❌ _reloadVueByPath failed:', err);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
346
382
|
// Configurar listener para HMR de componentes Vue
|
|
347
383
|
socket.on('HRMVue', async (/** @type {ComponentInfo} */ data) => {
|
|
348
384
|
try {
|
|
@@ -372,12 +408,31 @@ async function initSocket(retries = 0) {
|
|
|
372
408
|
console.log('🔄 HRMHelper recibido:', data);
|
|
373
409
|
console.log('📋 Archivo modificado:', data.filePath);
|
|
374
410
|
|
|
411
|
+
// moduleId: identificador canónico del módulo en el registry
|
|
412
|
+
// El servidor lo envía como el path del output (ej: /public/utils/math.js)
|
|
413
|
+
const moduleId = data.moduleId || data.filePath;
|
|
414
|
+
|
|
375
415
|
if (data?.strategy) {
|
|
376
416
|
switch (data.strategy) {
|
|
377
417
|
case 'self-accept': {
|
|
418
|
+
// El módulo acepta su propio reemplazo (import.meta.hot.accept)
|
|
378
419
|
try {
|
|
379
420
|
const timestamp = Date.now();
|
|
380
|
-
|
|
421
|
+
// Usar moduleId (path absoluto con /) en lugar de data.filePath (relativo)
|
|
422
|
+
// data.filePath relativo resuelve mal desde /__versa/initHRM.js
|
|
423
|
+
const newModule = await import(
|
|
424
|
+
`${moduleId}?t=${timestamp}`
|
|
425
|
+
);
|
|
426
|
+
// También notificar al registry por si hay consumers adicionales
|
|
427
|
+
const registry = window.__versaHMR;
|
|
428
|
+
if (registry && registry.hasObservers(moduleId)) {
|
|
429
|
+
const exportedValue =
|
|
430
|
+
newModule.default !== undefined
|
|
431
|
+
? newModule.default
|
|
432
|
+
: newModule;
|
|
433
|
+
registry.notifyUpdate(moduleId, exportedValue);
|
|
434
|
+
}
|
|
435
|
+
console.log(`✅ Self-accept HMR: ${moduleId}`);
|
|
381
436
|
return;
|
|
382
437
|
} catch (error) {
|
|
383
438
|
reportErrorToServer(
|
|
@@ -391,9 +446,48 @@ async function initSocket(retries = 0) {
|
|
|
391
446
|
break;
|
|
392
447
|
}
|
|
393
448
|
case 'propagate': {
|
|
449
|
+
// Re-importar el módulo con cache-bust y notificar al registry
|
|
394
450
|
try {
|
|
395
451
|
const timestamp = Date.now();
|
|
396
|
-
|
|
452
|
+
// Usar moduleId (path absoluto con /) en lugar de data.filePath (relativo)
|
|
453
|
+
// data.filePath relativo resuelve mal desde /__versa/initHRM.js
|
|
454
|
+
const newModule = await import(
|
|
455
|
+
`${moduleId}?t=${timestamp}`
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
// Extraer el valor exportado (default o namespace)
|
|
459
|
+
const exportedValue =
|
|
460
|
+
newModule.default !== undefined
|
|
461
|
+
? newModule.default
|
|
462
|
+
: newModule;
|
|
463
|
+
|
|
464
|
+
// Notificar al registry de VersaHMR si hay observers registrados
|
|
465
|
+
const registry = window.__versaHMR;
|
|
466
|
+
if (registry && registry.hasObservers(moduleId)) {
|
|
467
|
+
const notified = registry.notifyUpdate(
|
|
468
|
+
moduleId,
|
|
469
|
+
exportedValue,
|
|
470
|
+
);
|
|
471
|
+
if (notified) {
|
|
472
|
+
console.log(
|
|
473
|
+
`✅ HMR sin recarga: ${moduleId} actualizado via registry`,
|
|
474
|
+
);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
// Si los callbacks fallaron, hacer full-reload como safety net
|
|
478
|
+
console.warn(
|
|
479
|
+
`⚠️ Callbacks del registry fallaron para ${moduleId}, haciendo full-reload`,
|
|
480
|
+
);
|
|
481
|
+
window.location.reload();
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Sin observers en registry → la re-importación ya actualizó
|
|
486
|
+
// el módulo en el scope de ES modules del browser.
|
|
487
|
+
// Los consumers que hicieron import dinámico obtendrán la nueva versión.
|
|
488
|
+
console.log(
|
|
489
|
+
`✅ HMR propagado: ${moduleId} (sin observers en registry, re-import completado)`,
|
|
490
|
+
);
|
|
397
491
|
return;
|
|
398
492
|
} catch (error) {
|
|
399
493
|
reportErrorToServer(
|
|
@@ -403,8 +497,10 @@ async function initSocket(retries = 0) {
|
|
|
403
497
|
: new Error(String(error)),
|
|
404
498
|
data,
|
|
405
499
|
);
|
|
500
|
+
// Fallback a full-reload en caso de error
|
|
501
|
+
window.location.reload();
|
|
502
|
+
return;
|
|
406
503
|
}
|
|
407
|
-
break;
|
|
408
504
|
}
|
|
409
505
|
case 'full-reload':
|
|
410
506
|
default: {
|
|
@@ -453,18 +549,30 @@ async function initSocket(retries = 0) {
|
|
|
453
549
|
break;
|
|
454
550
|
|
|
455
551
|
case 'propagate':
|
|
456
|
-
// Propagar la actualización
|
|
552
|
+
// Propagar la actualización: re-importar y notificar al registry
|
|
457
553
|
console.log(
|
|
458
554
|
'🔄 Propagando actualización a importadores',
|
|
459
555
|
);
|
|
460
556
|
try {
|
|
461
|
-
// Invalidar el módulo en el cache del navegador
|
|
462
|
-
// y dejar que los importadores se actualicen
|
|
463
557
|
const timestamp = Date.now();
|
|
464
|
-
await import(
|
|
465
|
-
|
|
466
|
-
'✅ Actualización propagada exitosamente',
|
|
558
|
+
const newModule = await import(
|
|
559
|
+
`${data.filePath}?t=${timestamp}`
|
|
467
560
|
);
|
|
561
|
+
const exportedValue =
|
|
562
|
+
newModule.default !== undefined
|
|
563
|
+
? newModule.default
|
|
564
|
+
: newModule;
|
|
565
|
+
const registry = window.__versaHMR;
|
|
566
|
+
if (registry && registry.hasObservers(moduleId)) {
|
|
567
|
+
registry.notifyUpdate(moduleId, exportedValue);
|
|
568
|
+
console.log(
|
|
569
|
+
'✅ Actualización propagada via registry',
|
|
570
|
+
);
|
|
571
|
+
} else {
|
|
572
|
+
console.log(
|
|
573
|
+
'✅ Re-import completado (sin observers en registry)',
|
|
574
|
+
);
|
|
575
|
+
}
|
|
468
576
|
return;
|
|
469
577
|
} catch (error) {
|
|
470
578
|
console.error(
|
|
@@ -0,0 +1,317 @@
|
|
|
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
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @fileoverview VersaHMR — Registry de módulos para Hot Module Replacement
|
|
15
|
+
*
|
|
16
|
+
* Permite que librerías y utilidades JS/TS reciban actualizaciones sin full-reload.
|
|
17
|
+
*
|
|
18
|
+
* Uso básico (en cualquier módulo que consuma una librería):
|
|
19
|
+
*
|
|
20
|
+
* window.__versaHMR.accept('/public/utils/math.js', (newModule) => {
|
|
21
|
+
* // Recibir la nueva versión y actualizar referencias locales
|
|
22
|
+
* mathLib = newModule;
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* Uso automático (para módulos que solo exportan funciones/constantes):
|
|
26
|
+
* El sistema detecta automáticamente si es seguro hacer HMR y llama a los callbacks.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} ModuleEntry
|
|
31
|
+
* @property {any} module - La instancia actual del módulo
|
|
32
|
+
* @property {Set<Function>} callbacks - Callbacks registrados para actualizaciones
|
|
33
|
+
* @property {number} version - Versión (incrementa en cada update)
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
class VersaModuleRegistry {
|
|
37
|
+
constructor() {
|
|
38
|
+
/** @type {Map<string, ModuleEntry>} */
|
|
39
|
+
this._registry = new Map();
|
|
40
|
+
|
|
41
|
+
/** @type {Map<string, Set<string>>} Árbol inverso: módulo → quién lo importa */
|
|
42
|
+
this._importers = new Map();
|
|
43
|
+
|
|
44
|
+
/** @type {Set<string>} Módulos que han fallado al actualizarse */
|
|
45
|
+
this._failedUpdates = new Set();
|
|
46
|
+
|
|
47
|
+
/** @type {Map<string, Set<Function>>} Callbacks de cleanup por módulo */
|
|
48
|
+
this._disposeCallbacks = new Map();
|
|
49
|
+
|
|
50
|
+
/** @type {Map<string, Object>} Datos persistentes entre ciclos HMR */
|
|
51
|
+
this._hotData = new Map();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Normaliza un moduleId para uso como clave en el registry.
|
|
56
|
+
* Elimina query params y asegura formato consistente.
|
|
57
|
+
* @param {string} moduleId
|
|
58
|
+
* @returns {string}
|
|
59
|
+
*/
|
|
60
|
+
_normalizeId(moduleId) {
|
|
61
|
+
try {
|
|
62
|
+
// Si es una URL relativa, la convertimos a pathname limpio
|
|
63
|
+
const url = new URL(moduleId, window.location.origin);
|
|
64
|
+
return url.pathname;
|
|
65
|
+
} catch {
|
|
66
|
+
return moduleId.split('?')[0];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Registra un callback para recibir actualizaciones de un módulo.
|
|
72
|
+
* El callback se llama con (newModule, { moduleId, version }) cuando el módulo cambia.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} moduleId - Path/URL del módulo a observar (ej: '/public/utils/math.js')
|
|
75
|
+
* @param {Function} updateCallback - Función llamada cuando el módulo cambia
|
|
76
|
+
* @returns {Function} Función para cancelar el registro (unsubscribe)
|
|
77
|
+
*/
|
|
78
|
+
accept(moduleId, updateCallback) {
|
|
79
|
+
const id = this._normalizeId(moduleId);
|
|
80
|
+
|
|
81
|
+
if (!this._registry.has(id)) {
|
|
82
|
+
this._registry.set(id, {
|
|
83
|
+
module: null,
|
|
84
|
+
callbacks: new Set(),
|
|
85
|
+
version: 0,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const entry = this._registry.get(id);
|
|
90
|
+
entry.callbacks.add(updateCallback);
|
|
91
|
+
|
|
92
|
+
console.log(`[VersaHMR] Registrado observer para: ${id}`);
|
|
93
|
+
|
|
94
|
+
// Retornar función de cleanup
|
|
95
|
+
return () => {
|
|
96
|
+
const e = this._registry.get(id);
|
|
97
|
+
if (e) {
|
|
98
|
+
e.callbacks.delete(updateCallback);
|
|
99
|
+
if (e.callbacks.size === 0) {
|
|
100
|
+
this._registry.delete(id);
|
|
101
|
+
console.log(`[VersaHMR] Registry limpiado para: ${id}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Notifica a todos los observers registrados que un módulo fue actualizado.
|
|
109
|
+
* Llamado internamente por el handler de HRMHelper cuando recibe un nuevo módulo.
|
|
110
|
+
*
|
|
111
|
+
* @param {string} moduleId - Path del módulo actualizado
|
|
112
|
+
* @param {any} newModule - La nueva instancia del módulo exportado
|
|
113
|
+
* @returns {boolean} true si había al menos un observer y todos ejecutaron sin error
|
|
114
|
+
*/
|
|
115
|
+
notifyUpdate(moduleId, newModule) {
|
|
116
|
+
const id = this._normalizeId(moduleId);
|
|
117
|
+
const entry = this._registry.get(id);
|
|
118
|
+
|
|
119
|
+
if (!entry || entry.callbacks.size === 0) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Ejecutar dispose callbacks antes de actualizar
|
|
124
|
+
this._runDispose(id);
|
|
125
|
+
|
|
126
|
+
entry.version++;
|
|
127
|
+
entry.module = newModule;
|
|
128
|
+
const meta = { moduleId: id, version: entry.version };
|
|
129
|
+
|
|
130
|
+
let allSucceeded = true;
|
|
131
|
+
|
|
132
|
+
for (const callback of entry.callbacks) {
|
|
133
|
+
try {
|
|
134
|
+
callback(newModule, meta);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error(
|
|
137
|
+
`[VersaHMR] Error en callback de update para ${id}:`,
|
|
138
|
+
err,
|
|
139
|
+
);
|
|
140
|
+
allSucceeded = false;
|
|
141
|
+
this._failedUpdates.add(id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (allSucceeded) {
|
|
146
|
+
this._failedUpdates.delete(id);
|
|
147
|
+
console.log(
|
|
148
|
+
`[VersaHMR] ✅ Módulo actualizado (v${entry.version}): ${id} — ${entry.callbacks.size} observer(s) notificado(s)`,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return allSucceeded;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Registra la relación de importación entre módulos.
|
|
157
|
+
* Esto permite propagación en cadena cuando cambia un módulo.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} importer - Path del módulo que importa
|
|
160
|
+
* @param {string} imported - Path del módulo importado
|
|
161
|
+
*/
|
|
162
|
+
registerImporter(importer, imported) {
|
|
163
|
+
const importedId = this._normalizeId(imported);
|
|
164
|
+
const importerId = this._normalizeId(importer);
|
|
165
|
+
|
|
166
|
+
if (!this._importers.has(importedId)) {
|
|
167
|
+
this._importers.set(importedId, new Set());
|
|
168
|
+
}
|
|
169
|
+
this._importers.get(importedId).add(importerId);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Obtiene el módulo actual registrado (si fue cargado via notifyUpdate).
|
|
174
|
+
* @param {string} moduleId
|
|
175
|
+
* @returns {any | null}
|
|
176
|
+
*/
|
|
177
|
+
getModule(moduleId) {
|
|
178
|
+
const id = this._normalizeId(moduleId);
|
|
179
|
+
return this._registry.get(id)?.module ?? null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Registra un callback de dispose que se ejecuta antes de que el módulo
|
|
184
|
+
* sea reemplazado. Permite cleanup de timers, event listeners, etc.
|
|
185
|
+
* Expuesto como import.meta.hot.dispose(cb) en el shim de HMR.
|
|
186
|
+
*
|
|
187
|
+
* @param {string} moduleId
|
|
188
|
+
* @param {Function} cb - Llamado con (data) donde data = _getHotData(moduleId)
|
|
189
|
+
*/
|
|
190
|
+
_onDispose(moduleId, cb) {
|
|
191
|
+
const id = this._normalizeId(moduleId);
|
|
192
|
+
if (!this._disposeCallbacks.has(id)) {
|
|
193
|
+
this._disposeCallbacks.set(id, new Set());
|
|
194
|
+
}
|
|
195
|
+
this._disposeCallbacks.get(id).add(cb);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Retorna el objeto de datos persistentes de un módulo.
|
|
200
|
+
* El objeto sobrevive entre ciclos HMR para preservar estado local.
|
|
201
|
+
* Expuesto como import.meta.hot.data en el shim de HMR.
|
|
202
|
+
*
|
|
203
|
+
* @param {string} moduleId
|
|
204
|
+
* @returns {Object}
|
|
205
|
+
*/
|
|
206
|
+
_getHotData(moduleId) {
|
|
207
|
+
const id = this._normalizeId(moduleId);
|
|
208
|
+
if (!this._hotData.has(id)) {
|
|
209
|
+
this._hotData.set(id, {});
|
|
210
|
+
}
|
|
211
|
+
return this._hotData.get(id);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Ejecuta los callbacks de dispose antes de un update HMR.
|
|
216
|
+
* Llamado internamente desde notifyUpdate antes de notificar observers.
|
|
217
|
+
*
|
|
218
|
+
* @param {string} moduleId
|
|
219
|
+
*/
|
|
220
|
+
_runDispose(moduleId) {
|
|
221
|
+
const id = this._normalizeId(moduleId);
|
|
222
|
+
const disposers = this._disposeCallbacks.get(id);
|
|
223
|
+
if (!disposers || disposers.size === 0) return;
|
|
224
|
+
|
|
225
|
+
const data = this._getHotData(id);
|
|
226
|
+
for (const cb of disposers) {
|
|
227
|
+
try {
|
|
228
|
+
cb(data);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
console.error(
|
|
231
|
+
`[VersaHMR] Error en dispose callback para ${id}:`,
|
|
232
|
+
err,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
this._disposeCallbacks.delete(id);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Invalida un módulo: ejecuta dispose callbacks y fuerza recarga de página.
|
|
241
|
+
* Expuesto como import.meta.hot.invalidate() en el shim de HMR.
|
|
242
|
+
*
|
|
243
|
+
* @param {string} moduleId
|
|
244
|
+
*/
|
|
245
|
+
_invalidate(moduleId) {
|
|
246
|
+
const id = this._normalizeId(moduleId);
|
|
247
|
+
|
|
248
|
+
// Ejecutar dispose callbacks antes de invalidar
|
|
249
|
+
this._runDispose(id);
|
|
250
|
+
|
|
251
|
+
// Limpiar estado del módulo
|
|
252
|
+
this._hotData.delete(id);
|
|
253
|
+
this._registry.delete(id);
|
|
254
|
+
|
|
255
|
+
console.log(
|
|
256
|
+
`[VersaHMR] Módulo invalidado: ${id} — forzando recarga completa`,
|
|
257
|
+
);
|
|
258
|
+
window.location.reload();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Indica si un módulo tiene observers registrados (puede hacer HMR).
|
|
263
|
+
* @param {string} moduleId
|
|
264
|
+
* @returns {boolean}
|
|
265
|
+
*/
|
|
266
|
+
hasObservers(moduleId) {
|
|
267
|
+
const id = this._normalizeId(moduleId);
|
|
268
|
+
const entry = this._registry.get(id);
|
|
269
|
+
return !!(entry && entry.callbacks.size > 0);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Indica si un módulo tuvo fallos en el último update.
|
|
274
|
+
* @param {string} moduleId
|
|
275
|
+
* @returns {boolean}
|
|
276
|
+
*/
|
|
277
|
+
hasFailed(moduleId) {
|
|
278
|
+
return this._failedUpdates.has(this._normalizeId(moduleId));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Limpia todos los registros (útil para tests o hot-reload del propio sistema).
|
|
283
|
+
*/
|
|
284
|
+
clear() {
|
|
285
|
+
this._registry.clear();
|
|
286
|
+
this._importers.clear();
|
|
287
|
+
this._failedUpdates.clear();
|
|
288
|
+
this._disposeCallbacks.clear();
|
|
289
|
+
this._hotData.clear();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Estadísticas del registry (para debugging).
|
|
294
|
+
* @returns {{ modules: number, totalObservers: number, failedModules: number }}
|
|
295
|
+
*/
|
|
296
|
+
getStats() {
|
|
297
|
+
let totalObservers = 0;
|
|
298
|
+
for (const entry of this._registry.values()) {
|
|
299
|
+
totalObservers += entry.callbacks.size;
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
modules: this._registry.size,
|
|
303
|
+
totalObservers,
|
|
304
|
+
failedModules: this._failedUpdates.size,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Singleton global expuesto en window.__versaHMR
|
|
310
|
+
// Se preserva entre recargas parciales para no perder observers
|
|
311
|
+
if (!window.__versaHMR) {
|
|
312
|
+
window.__versaHMR = new VersaModuleRegistry();
|
|
313
|
+
console.log('[VersaHMR] Registry inicializado');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export const versaHMR = window.__versaHMR;
|
|
317
|
+
export default versaHMR;
|
package/dist/main.js
CHANGED
|
@@ -259,6 +259,13 @@ async function main() {
|
|
|
259
259
|
try {
|
|
260
260
|
// Verificar si el archivo existe
|
|
261
261
|
await fs.access(file);
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
logger.error(chalk.red(`❌ El archivo '${file}' no existe.`));
|
|
265
|
+
hasErrors = true;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
262
269
|
logger.info(chalk.blue(`🔄 Compilando: ${file}`));
|
|
263
270
|
const result = await compileFile(file);
|
|
264
271
|
if (result.success) {
|
|
@@ -269,8 +276,8 @@ async function main() {
|
|
|
269
276
|
hasErrors = true;
|
|
270
277
|
}
|
|
271
278
|
}
|
|
272
|
-
catch {
|
|
273
|
-
logger.error(chalk.red(`❌
|
|
279
|
+
catch (err) {
|
|
280
|
+
logger.error(chalk.red(`❌ Error al compilar '${file}': ${err instanceof Error ? err.message : String(err)}`));
|
|
274
281
|
hasErrors = true;
|
|
275
282
|
}
|
|
276
283
|
}
|