versacompiler 2.4.1 → 2.6.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.
- package/README.md +722 -722
- package/dist/compiler/compile-worker-pool.js +108 -0
- package/dist/compiler/compile-worker-thread.cjs +72 -0
- package/dist/compiler/compile.js +177 -18
- package/dist/compiler/error-reporter.js +12 -0
- package/dist/compiler/integrity-validator.js +13 -1
- 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 +35 -20
- package/dist/compiler/parser.js +12 -0
- package/dist/compiler/performance-monitor.js +73 -61
- package/dist/compiler/pipeline/build-pipeline.js +139 -0
- package/dist/compiler/pipeline/core-plugins.js +230 -0
- package/dist/compiler/pipeline/module-graph.js +75 -0
- package/dist/compiler/pipeline/plugin-driver.js +99 -0
- package/dist/compiler/pipeline/types.js +14 -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 +234 -16
- package/dist/compiler/typescript-compiler.js +12 -0
- package/dist/compiler/typescript-error-parser.js +12 -0
- package/dist/compiler/typescript-manager.js +15 -1
- package/dist/compiler/typescript-sync-validator.js +45 -31
- package/dist/compiler/typescript-worker-pool.js +12 -0
- package/dist/compiler/typescript-worker-thread.cjs +482 -475
- package/dist/compiler/typescript-worker.js +12 -0
- package/dist/compiler/vuejs.js +73 -47
- package/dist/config.js +14 -0
- package/dist/hrm/VueHRM.js +484 -359
- package/dist/hrm/errorScreen.js +95 -83
- package/dist/hrm/getInstanciaVue.js +325 -313
- package/dist/hrm/initHRM.js +736 -586
- package/dist/hrm/versaHMR.js +317 -0
- package/dist/main.js +23 -3
- package/dist/servicios/browserSync.js +127 -6
- package/dist/servicios/file-watcher.js +139 -8
- package/dist/servicios/logger.js +12 -0
- package/dist/servicios/readConfig.js +141 -54
- package/dist/servicios/versacompile.config.types.js +14 -0
- package/dist/utils/excluded-modules.js +12 -0
- package/dist/utils/module-resolver.js +86 -40
- 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 +260 -248
- package/dist/wrappers/eslint-node.js +15 -1
- package/dist/wrappers/oxlint-node.js +15 -1
- package/dist/wrappers/tailwind-node.js +12 -0
- package/package.json +74 -54
package/dist/hrm/VueHRM.js
CHANGED
|
@@ -1,359 +1,484 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @typedef {Object}
|
|
15
|
-
* @property {
|
|
16
|
-
* @property {Object}
|
|
17
|
-
* @property {
|
|
18
|
-
* @property {
|
|
19
|
-
* @property {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* @
|
|
27
|
-
* @property {Object} [
|
|
28
|
-
* @property {
|
|
29
|
-
* @property {
|
|
30
|
-
* @property {
|
|
31
|
-
* @property {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* @
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* @
|
|
40
|
-
* @property {
|
|
41
|
-
* @property {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* @
|
|
46
|
-
* @property {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
* @
|
|
52
|
-
* @
|
|
53
|
-
* @
|
|
54
|
-
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
*
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
return false;
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
+
* @typedef {Object} TreeNode
|
|
15
|
+
* @property {string} name - Nombre del componente
|
|
16
|
+
* @property {Object} instancia - Instancia del componente Vue
|
|
17
|
+
* @property {TreeNode[]} children - Nodos hijos
|
|
18
|
+
* @property {TreeNode|null} parent - Nodo padre
|
|
19
|
+
* @property {boolean} isRoot - Si es el nodo raíz
|
|
20
|
+
* @property {string} [from] - Origen del nodo
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { obtenerInstanciaVue } from './getInstanciaVue.js';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {Object} VNode
|
|
27
|
+
* @property {Object} [type] - Tipo del VNode
|
|
28
|
+
* @property {Object} [component] - Componente asociado
|
|
29
|
+
* @property {VNode[]} [children] - VNodes hijos
|
|
30
|
+
* @property {VNode[]} [dynamicChildren] - VNodes dinámicos
|
|
31
|
+
* @property {Object} [suspense] - Objeto suspense
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @typedef {Object} ComponentInstance
|
|
36
|
+
* @property {Object} type - Tipo del componente
|
|
37
|
+
* @property {string} [type.name] - Nombre del tipo
|
|
38
|
+
* @property {string} [type.__name] - Nombre alternativo del tipo
|
|
39
|
+
* @property {Object} [components] - Componentes registrados
|
|
40
|
+
* @property {VNode} subTree - Subárbol del componente
|
|
41
|
+
* @property {Object} [proxy] - Proxy del componente
|
|
42
|
+
* @property {Function} [proxy.$forceUpdate] - Función de actualización forzada
|
|
43
|
+
* @property {Function} [update] - Función de actualización
|
|
44
|
+
* @property {Object} [ctx] - Contexto del componente
|
|
45
|
+
* @property {Object} [ctx._] - Contexto interno del componente
|
|
46
|
+
* @property {Object} [ctx._.setupState] - Estado del setup del componente
|
|
47
|
+
* @property {number} [ctx._.setupState.versaComponentKey] - Clave del componente para HMR
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @typedef {Object} ComponentInfo
|
|
52
|
+
* @property {string} normalizedPath - Ruta normalizada del componente
|
|
53
|
+
* @property {string} nameFile - Nombre del archivo del componente
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {Object} VueApp
|
|
58
|
+
* @property {ComponentInstance} _instance - Instancia principal de la aplicación
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Busca nodos en el árbol por nombre de instancia
|
|
63
|
+
* @param {TreeNode} tree - Árbol de componentes
|
|
64
|
+
* @param {string} instance - Nombre de la instancia a buscar
|
|
65
|
+
* @returns {TreeNode[]} Array de nodos encontrados
|
|
66
|
+
*/
|
|
67
|
+
function findNodeByInstance(tree, instance) {
|
|
68
|
+
const matches = [];
|
|
69
|
+
/**
|
|
70
|
+
* @param {TreeNode} node - Nodo a buscar recursivamente
|
|
71
|
+
*/
|
|
72
|
+
function searchRecursively(node) {
|
|
73
|
+
if (node.name === instance) {
|
|
74
|
+
matches.push(node);
|
|
75
|
+
}
|
|
76
|
+
for (const child of node.children) {
|
|
77
|
+
searchRecursively(child);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
searchRecursively(tree);
|
|
82
|
+
return matches;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Obtiene el camino desde un nodo hasta la raíz
|
|
86
|
+
* @param {TreeNode} node - Nodo inicial
|
|
87
|
+
* @returns {TreeNode[]} Camino desde el nodo hasta la raíz
|
|
88
|
+
*/
|
|
89
|
+
function getPathToRoot(node) {
|
|
90
|
+
const path = [];
|
|
91
|
+
while (node) {
|
|
92
|
+
path.push(node);
|
|
93
|
+
node = node.parent;
|
|
94
|
+
}
|
|
95
|
+
return path; // Ordenado desde hijo hasta raíz
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Encuentra componentes recursivamente dentro de un VNode
|
|
100
|
+
* @param {VNode} vnode - VNode a explorar
|
|
101
|
+
* @param {TreeNode} parentTreeNode - Nodo padre en el árbol
|
|
102
|
+
*/
|
|
103
|
+
function recursivelyFindComponentsInVNode(vnode, parentTreeNode) {
|
|
104
|
+
if (!vnode || typeof vnode !== 'object') {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (vnode?.type.name === 'Suspense') {
|
|
108
|
+
const childComponentInstance = vnode?.suspense.activeBranch;
|
|
109
|
+
const childTreeNode = {
|
|
110
|
+
name: vnode?.type.name,
|
|
111
|
+
instancia: childComponentInstance,
|
|
112
|
+
children: [],
|
|
113
|
+
parent: parentTreeNode,
|
|
114
|
+
isRoot: false,
|
|
115
|
+
};
|
|
116
|
+
parentTreeNode.children.push(childTreeNode);
|
|
117
|
+
recursivelyFindComponentsInVNode(childComponentInstance, childTreeNode);
|
|
118
|
+
} else if (vnode.component) {
|
|
119
|
+
const childComponentInstance = vnode.component;
|
|
120
|
+
|
|
121
|
+
let componentName = 'Anonymous';
|
|
122
|
+
if (childComponentInstance.type) {
|
|
123
|
+
if (childComponentInstance.type.name) {
|
|
124
|
+
componentName = childComponentInstance.type.name;
|
|
125
|
+
} else if (childComponentInstance.type.__name) {
|
|
126
|
+
componentName = childComponentInstance.type.__name;
|
|
127
|
+
} else if (typeof childComponentInstance.type === 'function') {
|
|
128
|
+
const funcName = childComponentInstance.type.name;
|
|
129
|
+
if (funcName && funcName !== 'Anonymous function') {
|
|
130
|
+
componentName = funcName;
|
|
131
|
+
}
|
|
132
|
+
// Heurísticas para componentes comunes de Vue
|
|
133
|
+
const typeStr = childComponentInstance.type.toString();
|
|
134
|
+
if (typeStr.includes('BaseTransition')) {
|
|
135
|
+
componentName = 'Transition';
|
|
136
|
+
} else if (typeStr.includes('KeepAlive')) {
|
|
137
|
+
componentName = 'KeepAlive';
|
|
138
|
+
} else if (typeStr.includes('Suspense')) {
|
|
139
|
+
componentName = 'Suspense';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const childTreeNode = {
|
|
145
|
+
name: componentName,
|
|
146
|
+
instancia: childComponentInstance,
|
|
147
|
+
children: [],
|
|
148
|
+
parent: parentTreeNode,
|
|
149
|
+
isRoot: false,
|
|
150
|
+
};
|
|
151
|
+
parentTreeNode.children.push(childTreeNode);
|
|
152
|
+
traverseComponentInstance(childComponentInstance, childTreeNode);
|
|
153
|
+
} else {
|
|
154
|
+
const childrenToExplore = vnode.children || vnode.dynamicChildren;
|
|
155
|
+
if (Array.isArray(childrenToExplore)) {
|
|
156
|
+
childrenToExplore.forEach(childVNode => {
|
|
157
|
+
recursivelyFindComponentsInVNode(childVNode, parentTreeNode);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Recorre una instancia de componente y construye el árbol
|
|
165
|
+
* @param {ComponentInstance} componentInstance - Instancia del componente
|
|
166
|
+
* @param {TreeNode} currentTreeNode - Nodo actual del árbol
|
|
167
|
+
*/
|
|
168
|
+
function traverseComponentInstance(componentInstance, currentTreeNode) {
|
|
169
|
+
const subTreeVNode = componentInstance.subTree;
|
|
170
|
+
|
|
171
|
+
if (!subTreeVNode) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
recursivelyFindComponentsInVNode(subTreeVNode, currentTreeNode);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Construye el árbol de componentes desde una instancia raíz
|
|
180
|
+
* @param {ComponentInstance} componentRootInstance - Instancia raíz del componente
|
|
181
|
+
* @returns {TreeNode|null} Árbol de componentes o null si falla
|
|
182
|
+
*/
|
|
183
|
+
export const buildComponentTree = componentRootInstance => {
|
|
184
|
+
if (!componentRootInstance || !componentRootInstance.type) {
|
|
185
|
+
console.warn(
|
|
186
|
+
'No se pudo construir el árbol de componentes: instancia inválida',
|
|
187
|
+
);
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
const tree = {
|
|
191
|
+
name:
|
|
192
|
+
componentRootInstance.type?.name ||
|
|
193
|
+
componentRootInstance.type?.__name ||
|
|
194
|
+
'Anonymous',
|
|
195
|
+
instancia: componentRootInstance,
|
|
196
|
+
children: [],
|
|
197
|
+
parent: null,
|
|
198
|
+
isRoot: true,
|
|
199
|
+
from: 'root',
|
|
200
|
+
};
|
|
201
|
+
traverseComponentInstance(componentRootInstance, tree);
|
|
202
|
+
|
|
203
|
+
return tree;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Intenta forzar la actualización de una instancia de componente
|
|
208
|
+
* @param {ComponentInstance} instance - Instancia del componente a actualizar
|
|
209
|
+
* @returns {boolean} True si la actualización fue exitosa, false en caso contrario
|
|
210
|
+
*/
|
|
211
|
+
function tryForceUpdate(instance) {
|
|
212
|
+
if (!instance) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
if (instance.proxy && typeof instance.proxy.$forceUpdate === 'function') {
|
|
216
|
+
instance.proxy.$forceUpdate();
|
|
217
|
+
if (typeof instance.update === 'function') {
|
|
218
|
+
instance.update();
|
|
219
|
+
}
|
|
220
|
+
// buscar una variable en el componente que se llame versaComponentKey y sumarle 1
|
|
221
|
+
if (instance.ctx?._.setupState?.versaComponentKey !== undefined) {
|
|
222
|
+
instance.ctx._.setupState.versaComponentKey++;
|
|
223
|
+
}
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
if (typeof instance.update === 'function') {
|
|
227
|
+
if (instance.ctx?._.setupState?.versaComponentKey !== undefined) {
|
|
228
|
+
instance.ctx._.setupState.versaComponentKey++;
|
|
229
|
+
}
|
|
230
|
+
instance.update();
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
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
|
+
*
|
|
311
|
+
* @param {TreeNode[]} path - Camino de nodos desde el componente hasta la raíz
|
|
312
|
+
* @param {Object} newComponent - Nuevo componente a usar
|
|
313
|
+
* @param {string} componentName - Nombre del componente
|
|
314
|
+
* @param {VueApp} App - Aplicación Vue
|
|
315
|
+
* @returns {boolean} True si la actualización fue exitosa
|
|
316
|
+
*/
|
|
317
|
+
function tryUpdateComponentPath(path, newComponent, componentName, App) {
|
|
318
|
+
if (!path || !newComponent || !componentName || !App) {
|
|
319
|
+
console.error('❌ Parámetros inválidos para tryUpdateComponentPath');
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
|
|
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.
|
|
342
|
+
for (let i = 1; i < path.length; i++) {
|
|
343
|
+
const parent = path[i];
|
|
344
|
+
|
|
345
|
+
if (parent.isRoot || parent.name === 'KeepAlive') {
|
|
346
|
+
window.location.reload();
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (!parent?.instancia) {
|
|
351
|
+
console.error('❌ Nodo padre no válido en el camino:', parent);
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const componentsDefinition =
|
|
356
|
+
parent.instancia?.type?.components || parent.instancia?.components;
|
|
357
|
+
|
|
358
|
+
if (componentsDefinition && componentsDefinition[componentName]) {
|
|
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
|
+
}
|
|
372
|
+
|
|
373
|
+
return (
|
|
374
|
+
tryForceUpdate(parent.instancia) ||
|
|
375
|
+
tryForceUpdate(parent.instancia.proxy)
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Recarga un componente Vue con Hot Module Replacement
|
|
385
|
+
* @param {VueApp} App - Aplicación Vue principal
|
|
386
|
+
* @param {ComponentInfo} Component - Información del componente a recargar
|
|
387
|
+
* @returns {Promise<boolean>} Promise que resuelve a true si la recarga fue exitosa
|
|
388
|
+
*/
|
|
389
|
+
export async function reloadComponent(App, Component) {
|
|
390
|
+
try {
|
|
391
|
+
const { normalizedPath: relativePath, nameFile: componentName } =
|
|
392
|
+
Component;
|
|
393
|
+
if (!App || !App._instance) {
|
|
394
|
+
const vueInstance = await obtenerInstanciaVue();
|
|
395
|
+
if (!vueInstance) {
|
|
396
|
+
console.error('❌ No se pudo obtener la instancia de Vue');
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
App = vueInstance;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (!relativePath) {
|
|
403
|
+
console.error('❌ No se proporcionó relativePath');
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const baseUrl = window.location.href;
|
|
408
|
+
const newBaseUrl = new URL(baseUrl);
|
|
409
|
+
const urlOrigin = `${newBaseUrl.origin}/${relativePath}`;
|
|
410
|
+
const timestamp = Date.now();
|
|
411
|
+
const moduleUrl = `${urlOrigin}?t=${timestamp}`;
|
|
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
|
+
|
|
425
|
+
const module = await import(moduleUrl);
|
|
426
|
+
|
|
427
|
+
if (!module.default) {
|
|
428
|
+
console.error('❌ El módulo importado no tiene export default');
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const componentTree = buildComponentTree(App._instance);
|
|
433
|
+
if (!componentTree) {
|
|
434
|
+
console.error('❌ No se pudo construir el árbol de componentes');
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const targetNodes = findNodeByInstance(componentTree, componentName);
|
|
439
|
+
if (!targetNodes) {
|
|
440
|
+
console.warn(
|
|
441
|
+
'⚠️ No se encontró el nodo objetivo para:',
|
|
442
|
+
componentName,
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
console.log(
|
|
449
|
+
`🔍 Se encontraron ${targetNodes.length} instancias del componente ${componentName}`,
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
let successfulUpdates = 0; // Procesar TODAS las instancias encontradas
|
|
453
|
+
for (let i = 0; i < targetNodes.length; i++) {
|
|
454
|
+
const node = targetNodes[i];
|
|
455
|
+
if (node) {
|
|
456
|
+
const path = getPathToRoot(node);
|
|
457
|
+
const updateResult = await tryUpdateComponentPath(
|
|
458
|
+
path,
|
|
459
|
+
module.default,
|
|
460
|
+
componentName,
|
|
461
|
+
App,
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
if (updateResult) {
|
|
465
|
+
successfulUpdates++;
|
|
466
|
+
} else {
|
|
467
|
+
console.error(
|
|
468
|
+
`❌ No se pudo actualizar la instancia ${i + 1}`,
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const hasSuccessfulUpdate = successfulUpdates > 0;
|
|
475
|
+
console.log(
|
|
476
|
+
`\n📊 Resultado final: ${successfulUpdates}/${targetNodes.length} instancias actualizadas`,
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
return hasSuccessfulUpdate;
|
|
480
|
+
} catch (error) {
|
|
481
|
+
console.error('❌ Error en reloadComponent:', error);
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
}
|