versacompiler 2.4.0 → 2.5.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 +96 -0
- package/dist/compiler/compile-worker-thread.cjs +72 -0
- package/dist/compiler/compile.js +81 -2
- package/dist/compiler/integrity-validator.js +1 -1
- package/dist/compiler/module-resolution-optimizer.js +23 -20
- package/dist/compiler/performance-monitor.js +61 -61
- package/dist/compiler/pipeline/build-pipeline.js +127 -0
- package/dist/compiler/pipeline/core-plugins.js +218 -0
- package/dist/compiler/pipeline/module-graph.js +63 -0
- package/dist/compiler/pipeline/plugin-driver.js +87 -0
- package/dist/compiler/pipeline/types.js +2 -0
- package/dist/compiler/transforms.js +222 -16
- package/dist/compiler/typescript-manager.js +3 -1
- package/dist/compiler/typescript-sync-validator.js +33 -31
- package/dist/compiler/typescript-worker-pool.js +66 -19
- package/dist/compiler/typescript-worker-thread.cjs +482 -469
- package/dist/compiler/vuejs.js +32 -32
- package/dist/config.js +2 -0
- package/dist/hrm/VueHRM.js +359 -359
- package/dist/hrm/errorScreen.js +83 -83
- package/dist/hrm/getInstanciaVue.js +313 -313
- package/dist/hrm/initHRM.js +628 -586
- package/dist/main.js +2 -1
- package/dist/servicios/browserSync.js +8 -2
- package/dist/servicios/file-watcher.js +48 -6
- package/dist/servicios/readConfig.js +129 -54
- package/dist/servicios/versacompile.config.types.js +2 -0
- package/dist/utils/module-resolver.js +74 -40
- package/dist/utils/vue-types-setup.js +248 -248
- package/dist/wrappers/eslint-node.js +3 -1
- package/dist/wrappers/oxlint-node.js +3 -1
- package/package.json +73 -54
|
@@ -1,469 +1,482 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TypeScript Worker Thread - Ejecuta type checking asíncrono
|
|
3
|
-
* Este archivo se ejecuta en un worker thread separado para validación de tipos
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const fs = require('node:fs');
|
|
7
|
-
const path = require('node:path');
|
|
8
|
-
const { parentPort } = require('node:worker_threads');
|
|
9
|
-
|
|
10
|
-
// Debug: Log de inicio del worker
|
|
11
|
-
// console.log('[Worker] TypeScript Worker Thread iniciado');
|
|
12
|
-
|
|
13
|
-
let ts;
|
|
14
|
-
try {
|
|
15
|
-
ts = require('typescript');
|
|
16
|
-
// console.log('[Worker] TypeScript cargado exitosamente');
|
|
17
|
-
} catch (error) {
|
|
18
|
-
console.error('[Worker] Error cargando TypeScript:', error);
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Language Service Host para validación de tipos en el worker
|
|
24
|
-
*/
|
|
25
|
-
class WorkerTypeScriptLanguageServiceHost {
|
|
26
|
-
constructor(compilerOptions) {
|
|
27
|
-
this.files = new Map();
|
|
28
|
-
// Crear opciones ultra-limpias para evitar problemas de serialización
|
|
29
|
-
this.compilerOptions =
|
|
30
|
-
this.createUltraCleanCompilerOptions(compilerOptions);
|
|
31
|
-
} /**
|
|
32
|
-
* Crea opciones del compilador que respetan la configuración del tsconfig.json
|
|
33
|
-
*/
|
|
34
|
-
createUltraCleanCompilerOptions(options) {
|
|
35
|
-
// Usar las opciones del tsconfig.json pasadas desde el hilo principal
|
|
36
|
-
const cleanOptions = {
|
|
37
|
-
// target: options.target || ts.ScriptTarget.ES2020,
|
|
38
|
-
// module: options.module || ts.ModuleKind.ES2020,
|
|
39
|
-
// strict: Boolean(options.strict),
|
|
40
|
-
// noEmitOnError: Boolean(options.noEmitOnError),
|
|
41
|
-
// skipLibCheck: Boolean(options.skipLibCheck !== false), // true por defecto
|
|
42
|
-
// skipDefaultLibCheck: Boolean(options.skipDefaultLibCheck !== false), // true por defecto
|
|
43
|
-
// allowJs: Boolean(options.allowJs !== false), // true por defecto
|
|
44
|
-
// esModuleInterop: Boolean(options.esModuleInterop !== false), // true por defecto
|
|
45
|
-
// allowSyntheticDefaultImports: Boolean(
|
|
46
|
-
// options.allowSyntheticDefaultImports !== false,
|
|
47
|
-
// ), // true por defecto
|
|
48
|
-
// declaration: Boolean(options.declaration),
|
|
49
|
-
// sourceMap: Boolean(options.sourceMap),
|
|
50
|
-
// noImplicitAny: Boolean(options.noImplicitAny),
|
|
51
|
-
// noImplicitReturns: Boolean(options.noImplicitReturns),
|
|
52
|
-
// noImplicitThis: Boolean(options.noImplicitThis),
|
|
53
|
-
// noUnusedLocals: Boolean(options.noUnusedLocals),
|
|
54
|
-
// noUnusedParameters: Boolean(options.noUnusedParameters),
|
|
55
|
-
// isolatedModules: Boolean(options.isolatedModules !== false), // true por defecto // Usar las librerías especificadas en el tsconfig.json
|
|
56
|
-
// lib: Array.isArray(options.lib)
|
|
57
|
-
// ? options.lib
|
|
58
|
-
// : ['es2020', 'dom', 'dom.iterable'],
|
|
59
|
-
|
|
60
|
-
// // Soporte para decorators
|
|
61
|
-
// experimentalDecorators: Boolean(
|
|
62
|
-
// options.experimentalDecorators !== false,
|
|
63
|
-
// ),
|
|
64
|
-
// emitDecoratorMetadata: Boolean(
|
|
65
|
-
// options.emitDecoratorMetadata !== false,
|
|
66
|
-
// ),
|
|
67
|
-
|
|
68
|
-
// // Opciones críticas para el worker pero manteniendo compatibilidad
|
|
69
|
-
// noLib: false, // Permitir librerías para APIs básicas (DOM, Promise, etc.)
|
|
70
|
-
// noResolve: true, // Evitar resolución de módulos compleja pero mantener tipos globales
|
|
71
|
-
// suppressOutputPathCheck: true,
|
|
72
|
-
// allowNonTsExtensions: true,
|
|
73
|
-
...options,
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// console.log(
|
|
77
|
-
// '[Worker] Opciones del compilador recibidas:',
|
|
78
|
-
// Object.keys(cleanOptions),
|
|
79
|
-
// );
|
|
80
|
-
return cleanOptions;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
addFile(fileName, content) {
|
|
84
|
-
const existing = this.files.get(fileName);
|
|
85
|
-
this.files.set(fileName, {
|
|
86
|
-
version: existing ? existing.version + 1 : 1,
|
|
87
|
-
content,
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
getCompilationSettings() {
|
|
92
|
-
return this.compilerOptions;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
getScriptFileNames() {
|
|
96
|
-
return Array.from(this.files.keys());
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
getScriptVersion(fileName) {
|
|
100
|
-
const file = this.files.get(fileName);
|
|
101
|
-
return file ? file.version.toString() : '0';
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
getScriptSnapshot(fileName) {
|
|
105
|
-
const file = this.files.get(fileName);
|
|
106
|
-
if (file) {
|
|
107
|
-
return ts.ScriptSnapshot.fromString(file.content);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Intentar leer el archivo del sistema de archivos para dependencias
|
|
111
|
-
if (fs.existsSync(fileName)) {
|
|
112
|
-
try {
|
|
113
|
-
const content = fs.readFileSync(fileName, 'utf-8');
|
|
114
|
-
return ts.ScriptSnapshot.fromString(content);
|
|
115
|
-
} catch {
|
|
116
|
-
return undefined;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
getCurrentDirectory() {
|
|
124
|
-
return process.cwd();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
getDefaultLibFileName(options) {
|
|
128
|
-
return ts.getDefaultLibFilePath(options);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
fileExists(filePath) {
|
|
132
|
-
return this.files.has(filePath) || fs.existsSync(filePath);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
readFile(filePath) {
|
|
136
|
-
const file = this.files.get(filePath);
|
|
137
|
-
if (file) {
|
|
138
|
-
return file.content;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (fs.existsSync(filePath)) {
|
|
142
|
-
try {
|
|
143
|
-
return fs.readFileSync(filePath, 'utf-8');
|
|
144
|
-
} catch {
|
|
145
|
-
return undefined;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
getNewLine() {
|
|
153
|
-
return ts.sys.newLine;
|
|
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
|
-
|
|
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
|
-
!messageText.includes(
|
|
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
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
//
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
//
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
//
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript Worker Thread - Ejecuta type checking asíncrono
|
|
3
|
+
* Este archivo se ejecuta en un worker thread separado para validación de tipos
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('node:fs');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
const { parentPort } = require('node:worker_threads');
|
|
9
|
+
|
|
10
|
+
// Debug: Log de inicio del worker
|
|
11
|
+
// console.log('[Worker] TypeScript Worker Thread iniciado');
|
|
12
|
+
|
|
13
|
+
let ts;
|
|
14
|
+
try {
|
|
15
|
+
ts = require('typescript');
|
|
16
|
+
// console.log('[Worker] TypeScript cargado exitosamente');
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error('[Worker] Error cargando TypeScript:', error);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Language Service Host para validación de tipos en el worker
|
|
24
|
+
*/
|
|
25
|
+
class WorkerTypeScriptLanguageServiceHost {
|
|
26
|
+
constructor(compilerOptions) {
|
|
27
|
+
this.files = new Map();
|
|
28
|
+
// Crear opciones ultra-limpias para evitar problemas de serialización
|
|
29
|
+
this.compilerOptions =
|
|
30
|
+
this.createUltraCleanCompilerOptions(compilerOptions);
|
|
31
|
+
} /**
|
|
32
|
+
* Crea opciones del compilador que respetan la configuración del tsconfig.json
|
|
33
|
+
*/
|
|
34
|
+
createUltraCleanCompilerOptions(options) {
|
|
35
|
+
// Usar las opciones del tsconfig.json pasadas desde el hilo principal
|
|
36
|
+
const cleanOptions = {
|
|
37
|
+
// target: options.target || ts.ScriptTarget.ES2020,
|
|
38
|
+
// module: options.module || ts.ModuleKind.ES2020,
|
|
39
|
+
// strict: Boolean(options.strict),
|
|
40
|
+
// noEmitOnError: Boolean(options.noEmitOnError),
|
|
41
|
+
// skipLibCheck: Boolean(options.skipLibCheck !== false), // true por defecto
|
|
42
|
+
// skipDefaultLibCheck: Boolean(options.skipDefaultLibCheck !== false), // true por defecto
|
|
43
|
+
// allowJs: Boolean(options.allowJs !== false), // true por defecto
|
|
44
|
+
// esModuleInterop: Boolean(options.esModuleInterop !== false), // true por defecto
|
|
45
|
+
// allowSyntheticDefaultImports: Boolean(
|
|
46
|
+
// options.allowSyntheticDefaultImports !== false,
|
|
47
|
+
// ), // true por defecto
|
|
48
|
+
// declaration: Boolean(options.declaration),
|
|
49
|
+
// sourceMap: Boolean(options.sourceMap),
|
|
50
|
+
// noImplicitAny: Boolean(options.noImplicitAny),
|
|
51
|
+
// noImplicitReturns: Boolean(options.noImplicitReturns),
|
|
52
|
+
// noImplicitThis: Boolean(options.noImplicitThis),
|
|
53
|
+
// noUnusedLocals: Boolean(options.noUnusedLocals),
|
|
54
|
+
// noUnusedParameters: Boolean(options.noUnusedParameters),
|
|
55
|
+
// isolatedModules: Boolean(options.isolatedModules !== false), // true por defecto // Usar las librerías especificadas en el tsconfig.json
|
|
56
|
+
// lib: Array.isArray(options.lib)
|
|
57
|
+
// ? options.lib
|
|
58
|
+
// : ['es2020', 'dom', 'dom.iterable'],
|
|
59
|
+
|
|
60
|
+
// // Soporte para decorators
|
|
61
|
+
// experimentalDecorators: Boolean(
|
|
62
|
+
// options.experimentalDecorators !== false,
|
|
63
|
+
// ),
|
|
64
|
+
// emitDecoratorMetadata: Boolean(
|
|
65
|
+
// options.emitDecoratorMetadata !== false,
|
|
66
|
+
// ),
|
|
67
|
+
|
|
68
|
+
// // Opciones críticas para el worker pero manteniendo compatibilidad
|
|
69
|
+
// noLib: false, // Permitir librerías para APIs básicas (DOM, Promise, etc.)
|
|
70
|
+
// noResolve: true, // Evitar resolución de módulos compleja pero mantener tipos globales
|
|
71
|
+
// suppressOutputPathCheck: true,
|
|
72
|
+
// allowNonTsExtensions: true,
|
|
73
|
+
...options,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// console.log(
|
|
77
|
+
// '[Worker] Opciones del compilador recibidas:',
|
|
78
|
+
// Object.keys(cleanOptions),
|
|
79
|
+
// );
|
|
80
|
+
return cleanOptions;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
addFile(fileName, content) {
|
|
84
|
+
const existing = this.files.get(fileName);
|
|
85
|
+
this.files.set(fileName, {
|
|
86
|
+
version: existing ? existing.version + 1 : 1,
|
|
87
|
+
content,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getCompilationSettings() {
|
|
92
|
+
return this.compilerOptions;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getScriptFileNames() {
|
|
96
|
+
return Array.from(this.files.keys());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
getScriptVersion(fileName) {
|
|
100
|
+
const file = this.files.get(fileName);
|
|
101
|
+
return file ? file.version.toString() : '0';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
getScriptSnapshot(fileName) {
|
|
105
|
+
const file = this.files.get(fileName);
|
|
106
|
+
if (file) {
|
|
107
|
+
return ts.ScriptSnapshot.fromString(file.content);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Intentar leer el archivo del sistema de archivos para dependencias
|
|
111
|
+
if (fs.existsSync(fileName)) {
|
|
112
|
+
try {
|
|
113
|
+
const content = fs.readFileSync(fileName, 'utf-8');
|
|
114
|
+
return ts.ScriptSnapshot.fromString(content);
|
|
115
|
+
} catch {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getCurrentDirectory() {
|
|
124
|
+
return process.cwd();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getDefaultLibFileName(options) {
|
|
128
|
+
return ts.getDefaultLibFilePath(options);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
fileExists(filePath) {
|
|
132
|
+
return this.files.has(filePath) || fs.existsSync(filePath);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
readFile(filePath) {
|
|
136
|
+
const file = this.files.get(filePath);
|
|
137
|
+
if (file) {
|
|
138
|
+
return file.content;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (fs.existsSync(filePath)) {
|
|
142
|
+
try {
|
|
143
|
+
return fs.readFileSync(filePath, 'utf-8');
|
|
144
|
+
} catch {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
getNewLine() {
|
|
153
|
+
return ts.sys.newLine;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Language Service persistente para reusar entre tareas (evita cold-start de 200-500ms por tarea)
|
|
159
|
+
* Se resetea periódicamente para controlar el uso de memoria
|
|
160
|
+
*/
|
|
161
|
+
let _persistentHost = null;
|
|
162
|
+
let _persistentLS = null;
|
|
163
|
+
let _persistentCompilerOptionsStr = null;
|
|
164
|
+
let _tasksSinceReset = 0;
|
|
165
|
+
const MAX_TASKS_BEFORE_LS_RESET = 50; // Resetear cada 50 tareas para controlar memoria
|
|
166
|
+
|
|
167
|
+
function getOrResetLanguageService(compilerOptions) {
|
|
168
|
+
const optionsStr = JSON.stringify(compilerOptions);
|
|
169
|
+
const needsReset =
|
|
170
|
+
!_persistentLS ||
|
|
171
|
+
optionsStr !== _persistentCompilerOptionsStr ||
|
|
172
|
+
_tasksSinceReset >= MAX_TASKS_BEFORE_LS_RESET;
|
|
173
|
+
|
|
174
|
+
if (needsReset) {
|
|
175
|
+
if (_persistentLS) {
|
|
176
|
+
try {
|
|
177
|
+
_persistentLS.dispose();
|
|
178
|
+
} catch {
|
|
179
|
+
/* ignore */
|
|
180
|
+
}
|
|
181
|
+
_persistentLS = null;
|
|
182
|
+
}
|
|
183
|
+
_persistentHost = new WorkerTypeScriptLanguageServiceHost(
|
|
184
|
+
compilerOptions,
|
|
185
|
+
);
|
|
186
|
+
_persistentLS = ts.createLanguageService(_persistentHost);
|
|
187
|
+
_persistentCompilerOptionsStr = optionsStr;
|
|
188
|
+
_tasksSinceReset = 0;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
_tasksSinceReset++;
|
|
192
|
+
return { host: _persistentHost, ls: _persistentLS };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Realiza validación de tipos en el worker thread
|
|
197
|
+
*/
|
|
198
|
+
function validateTypesInWorker(fileName, content, compilerOptions) {
|
|
199
|
+
let actualFileName = fileName;
|
|
200
|
+
try {
|
|
201
|
+
const scriptContent = content;
|
|
202
|
+
|
|
203
|
+
// Si el script está vacío o es solo espacios en blanco, no validar
|
|
204
|
+
if (!scriptContent.trim()) {
|
|
205
|
+
return { diagnostics: [], hasErrors: false };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Obtener o crear Language Service persistente (rápido después del primer uso)
|
|
209
|
+
const { host, ls: languageService } =
|
|
210
|
+
getOrResetLanguageService(compilerOptions);
|
|
211
|
+
|
|
212
|
+
// Para archivos Vue, crear un archivo virtual .ts
|
|
213
|
+
if (fileName.endsWith('.vue')) {
|
|
214
|
+
const virtualFileName = `${fileName}.ts`;
|
|
215
|
+
host.addFile(virtualFileName, scriptContent);
|
|
216
|
+
actualFileName = virtualFileName;
|
|
217
|
+
|
|
218
|
+
// Agregar declaraciones de tipos Vue si es necesario
|
|
219
|
+
const projectDir = path.dirname(actualFileName);
|
|
220
|
+
const vueTypesPath = path.join(projectDir, 'vue-types.d.ts');
|
|
221
|
+
const vueTypesDeclaration = `// Declaraciones de tipos Vue para validación
|
|
222
|
+
declare global {
|
|
223
|
+
function ref<T>(value: T): { value: T };
|
|
224
|
+
function reactive<T extends object>(target: T): T;
|
|
225
|
+
function computed<T>(getter: () => T): { value: T };
|
|
226
|
+
function defineComponent<T>(options: T): T;
|
|
227
|
+
function defineProps<T = {}>(): T;
|
|
228
|
+
function defineEmits<T = {}>(): T;
|
|
229
|
+
function defineExpose<T = {}>(exposed: T): void;
|
|
230
|
+
function mergeModels<T>(models: T): T;
|
|
231
|
+
function provide<T>(key: string | symbol, value: T): void;
|
|
232
|
+
function inject<T>(key: string | symbol, defaultValue?: T): T | undefined;
|
|
233
|
+
function useSlots(): { [key: string]: (...args: any[]) => any };
|
|
234
|
+
function useAttrs(): { [key: string]: any };
|
|
235
|
+
function useModel<T>(modelName: string): { value: T };
|
|
236
|
+
function onMounted(fn: () => void): void;
|
|
237
|
+
function onUnmounted(fn: () => void): void;
|
|
238
|
+
function watch<T>(source: () => T, callback: (newValue: T, oldValue: T) => void): void;
|
|
239
|
+
}
|
|
240
|
+
export {};`;
|
|
241
|
+
host.addFile(vueTypesPath, vueTypesDeclaration);
|
|
242
|
+
|
|
243
|
+
// Eliminar archivos de tareas anteriores para evitar que el programa crezca.
|
|
244
|
+
// Se hace DESPUÉS de addFile para que la versión se incremente correctamente
|
|
245
|
+
// (evita que el LS use resultados cacheados de versiones anteriores).
|
|
246
|
+
for (const key of host.files.keys()) {
|
|
247
|
+
if (key !== virtualFileName && key !== vueTypesPath) {
|
|
248
|
+
host.files.delete(key);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
host.addFile(fileName, scriptContent);
|
|
253
|
+
actualFileName = fileName;
|
|
254
|
+
|
|
255
|
+
// Eliminar archivos de tareas anteriores para evitar que el programa crezca.
|
|
256
|
+
// Se hace DESPUÉS de addFile para que la versión se incremente correctamente.
|
|
257
|
+
for (const key of host.files.keys()) {
|
|
258
|
+
if (key !== fileName) {
|
|
259
|
+
host.files.delete(key);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
// Verificar que el archivo existe en el host antes de solicitar diagnósticos
|
|
266
|
+
if (!host.fileExists(actualFileName)) {
|
|
267
|
+
return { diagnostics: [], hasErrors: false };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Obtener diagnósticos de tipos con manejo de errores
|
|
271
|
+
let syntacticDiagnostics = [];
|
|
272
|
+
let semanticDiagnostics = [];
|
|
273
|
+
try {
|
|
274
|
+
syntacticDiagnostics =
|
|
275
|
+
languageService.getSyntacticDiagnostics(actualFileName);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
console.error(
|
|
278
|
+
'[Worker] Error obteniendo diagnósticos sintácticos:',
|
|
279
|
+
error.message,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
semanticDiagnostics =
|
|
285
|
+
languageService.getSemanticDiagnostics(actualFileName);
|
|
286
|
+
} catch (error) {
|
|
287
|
+
console.error(
|
|
288
|
+
'[Worker] Error obteniendo diagnósticos semánticos:',
|
|
289
|
+
error.message,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const allDiagnostics = [
|
|
294
|
+
...syntacticDiagnostics,
|
|
295
|
+
...semanticDiagnostics,
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
// Filtrar diagnósticos relevantes
|
|
299
|
+
const filteredDiagnostics = allDiagnostics.filter(diag => {
|
|
300
|
+
const messageText = ts.flattenDiagnosticMessageText(
|
|
301
|
+
diag.messageText,
|
|
302
|
+
'\n',
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
// Solo errores de categoría Error
|
|
306
|
+
if (diag.category !== ts.DiagnosticCategory.Error) {
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Ignorar errores de infraestructura Vue y rutas de módulos
|
|
311
|
+
return (
|
|
312
|
+
!messageText.includes('Cannot find module') &&
|
|
313
|
+
!messageText.includes('Could not find source file') &&
|
|
314
|
+
!messageText.includes(
|
|
315
|
+
"has no exported member 'mergeModels'",
|
|
316
|
+
) &&
|
|
317
|
+
!messageText.includes(
|
|
318
|
+
"Parameter '$props' implicitly has an 'any' type",
|
|
319
|
+
) &&
|
|
320
|
+
!messageText.includes(
|
|
321
|
+
"Parameter '$setup' implicitly has an 'any' type",
|
|
322
|
+
) &&
|
|
323
|
+
!messageText.includes(
|
|
324
|
+
"Parameter '$data' implicitly has an 'any' type",
|
|
325
|
+
) &&
|
|
326
|
+
!messageText.includes(
|
|
327
|
+
"Parameter '$options' implicitly has an 'any' type",
|
|
328
|
+
) &&
|
|
329
|
+
!messageText.includes(
|
|
330
|
+
"Parameter '$event' implicitly has an 'any' type",
|
|
331
|
+
) &&
|
|
332
|
+
!messageText.includes(
|
|
333
|
+
"Parameter '_ctx' implicitly has an 'any' type",
|
|
334
|
+
) &&
|
|
335
|
+
!messageText.includes(
|
|
336
|
+
"Parameter '_cache' implicitly has an 'any' type",
|
|
337
|
+
) &&
|
|
338
|
+
!messageText.includes(
|
|
339
|
+
'Unable to resolve signature of method decorator when called as an expression',
|
|
340
|
+
) &&
|
|
341
|
+
!messageText.includes(
|
|
342
|
+
'The runtime will invoke the decorator with',
|
|
343
|
+
) &&
|
|
344
|
+
diag.code !== 1241 &&
|
|
345
|
+
!(
|
|
346
|
+
messageText.includes("implicitly has an 'any' type") &&
|
|
347
|
+
(messageText.includes('_ctx') ||
|
|
348
|
+
messageText.includes('_cache') ||
|
|
349
|
+
messageText.includes('$props') ||
|
|
350
|
+
messageText.includes('$setup') ||
|
|
351
|
+
messageText.includes('__expose') ||
|
|
352
|
+
messageText.includes('__emit'))
|
|
353
|
+
)
|
|
354
|
+
);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
diagnostics: filteredDiagnostics,
|
|
359
|
+
hasErrors: filteredDiagnostics.length > 0,
|
|
360
|
+
};
|
|
361
|
+
} catch {
|
|
362
|
+
return { diagnostics: [], hasErrors: false };
|
|
363
|
+
}
|
|
364
|
+
} catch (error) {
|
|
365
|
+
// En caso de error, devolver diagnóstico de error
|
|
366
|
+
const errorDiagnostic = {
|
|
367
|
+
file: undefined,
|
|
368
|
+
start: undefined,
|
|
369
|
+
length: undefined,
|
|
370
|
+
messageText: `Error en validación de tipos: ${error instanceof Error ? error.message : 'Error desconocido'}`,
|
|
371
|
+
category: ts.DiagnosticCategory.Error,
|
|
372
|
+
code: 0,
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
diagnostics: [errorDiagnostic],
|
|
377
|
+
hasErrors: true,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Escuchar mensajes del proceso principal
|
|
383
|
+
if (parentPort) {
|
|
384
|
+
parentPort.on('message', message => {
|
|
385
|
+
try {
|
|
386
|
+
// console.log('[Worker] Mensaje recibido:', {
|
|
387
|
+
// id: message.id,
|
|
388
|
+
// fileName: message.fileName,
|
|
389
|
+
// contentLength: message.content?.length,
|
|
390
|
+
// compilerOptions: Object.keys(message.compilerOptions || {}),
|
|
391
|
+
// });
|
|
392
|
+
|
|
393
|
+
const { id, fileName, content, compilerOptions } = message;
|
|
394
|
+
|
|
395
|
+
// Validar que el mensaje tiene la estructura correcta
|
|
396
|
+
if (!id || !fileName || typeof content !== 'string') {
|
|
397
|
+
parentPort.postMessage({
|
|
398
|
+
id: id || 'unknown',
|
|
399
|
+
success: false,
|
|
400
|
+
error: 'Mensaje del worker inválido',
|
|
401
|
+
});
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Realizar validación de tipos
|
|
406
|
+
const result = validateTypesInWorker(
|
|
407
|
+
fileName,
|
|
408
|
+
content,
|
|
409
|
+
compilerOptions,
|
|
410
|
+
); // Serializar diagnósticos de forma segura
|
|
411
|
+
const serializableDiagnostics = result.diagnostics.map(diag => ({
|
|
412
|
+
category: diag.category,
|
|
413
|
+
code: diag.code,
|
|
414
|
+
messageText:
|
|
415
|
+
typeof diag.messageText === 'string'
|
|
416
|
+
? diag.messageText
|
|
417
|
+
: ts.flattenDiagnosticMessageText(
|
|
418
|
+
diag.messageText,
|
|
419
|
+
'\n',
|
|
420
|
+
),
|
|
421
|
+
file: diag.file
|
|
422
|
+
? {
|
|
423
|
+
fileName: diag.file.fileName,
|
|
424
|
+
text: diag.file.text,
|
|
425
|
+
}
|
|
426
|
+
: undefined,
|
|
427
|
+
start: diag.start,
|
|
428
|
+
length: diag.length,
|
|
429
|
+
}));
|
|
430
|
+
|
|
431
|
+
// Enviar respuesta al proceso principal
|
|
432
|
+
// console.log('[Worker] Enviando respuesta:', {
|
|
433
|
+
// id,
|
|
434
|
+
// success: true,
|
|
435
|
+
// diagnosticsCount: serializableDiagnostics.length,
|
|
436
|
+
// hasErrors: result.hasErrors,
|
|
437
|
+
// });
|
|
438
|
+
|
|
439
|
+
parentPort.postMessage({
|
|
440
|
+
id,
|
|
441
|
+
success: true,
|
|
442
|
+
diagnostics: serializableDiagnostics,
|
|
443
|
+
hasErrors: result.hasErrors,
|
|
444
|
+
});
|
|
445
|
+
} catch (error) {
|
|
446
|
+
// Enviar error al proceso principal
|
|
447
|
+
parentPort.postMessage({
|
|
448
|
+
id: message?.id || 'unknown',
|
|
449
|
+
success: false,
|
|
450
|
+
error:
|
|
451
|
+
error instanceof Error
|
|
452
|
+
? error.message
|
|
453
|
+
: 'Error desconocido en worker',
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Manejar errores no capturados en el worker
|
|
460
|
+
process.on('uncaughtException', error => {
|
|
461
|
+
console.error('[Worker] Error no capturado en TypeScript worker:', error);
|
|
462
|
+
if (parentPort) {
|
|
463
|
+
parentPort.postMessage({
|
|
464
|
+
id: 'error',
|
|
465
|
+
success: false,
|
|
466
|
+
error: `Error crítico en worker: ${error.message}`,
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
process.exit(1);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// Log de confirmación de que el worker está listo
|
|
473
|
+
// console.log('[Worker] TypeScript Worker Thread listo para recibir mensajes');
|
|
474
|
+
|
|
475
|
+
// Señal de que el worker está listo
|
|
476
|
+
if (parentPort) {
|
|
477
|
+
parentPort.postMessage({
|
|
478
|
+
id: 'worker-ready',
|
|
479
|
+
success: true,
|
|
480
|
+
message: 'TypeScript worker iniciado correctamente',
|
|
481
|
+
});
|
|
482
|
+
}
|