versacompiler 2.0.4 → 2.0.5

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.
@@ -4,6 +4,7 @@ import * as process from 'node:process';
4
4
  import { env } from 'node:process';
5
5
  import * as typescript from 'typescript';
6
6
  import { createUnifiedErrorMessage, parseTypeScriptErrors, } from './typescript-error-parser.js';
7
+ import { validateTypesWithLanguageService } from './typescript-sync-validator.js';
7
8
  import { TypeScriptWorkerManager } from './typescript-worker.js';
8
9
  /**
9
10
  * Cache para la configuración de TypeScript para evitar lecturas repetidas
@@ -26,16 +27,8 @@ export const loadTypeScriptConfig = (fileName) => {
26
27
  try {
27
28
  const { config, error: configError } = typescript.readConfigFile(configPath, typescript.sys.readFile);
28
29
  if (!configError) {
29
- const parsedConfig = typescript.parseJsonConfigFileContent(config, typescript.sys, path.dirname(configPath));
30
- compilerOptions = {
31
- ...parsedConfig.options,
32
- // Asegurar opciones básicas necesarias
33
- allowJs: parsedConfig.options.allowJs !== false,
34
- esModuleInterop: parsedConfig.options.esModuleInterop !== false,
35
- allowSyntheticDefaultImports: parsedConfig.options.allowSyntheticDefaultImports !==
36
- false,
37
- skipLibCheck: parsedConfig.options.skipLibCheck !== false,
38
- };
30
+ const parsedConfig = typescript.parseJsonConfigFileContent(config, typescript.sys, path.dirname(configPath)); // Usar exactamente la configuración del tsconfig.json del usuario
31
+ compilerOptions = parsedConfig.options;
39
32
  }
40
33
  else {
41
34
  throw new Error(`Error al leer tsconfig.json: ${configError.messageText}`);
@@ -75,214 +68,14 @@ const getDefaultCompilerOptions = () => ({
75
68
  * @returns Opciones serializables seguras para workers
76
69
  */
77
70
  const createSerializableCompilerOptions = (options) => {
78
- // Usar las opciones del tsconfig.json pero con optimizaciones para el worker
79
- const { target = typescript.ScriptTarget.ES2020, module = typescript.ModuleKind.ES2020, lib = ['es2020', 'dom', 'dom.iterable'], allowJs = true, jsx, strict = false, skipLibCheck = true, esModuleInterop = true, allowSyntheticDefaultImports = true, isolatedModules = true, } = options;
71
+ // Respetar completamente la configuración del usuario del tsconfig.json
80
72
  return {
81
- target,
82
- module,
83
- lib: Array.isArray(lib) ? lib : ['es2020', 'dom', 'dom.iterable'],
84
- allowJs,
85
- jsx,
86
- strict,
87
- skipLibCheck,
88
- skipDefaultLibCheck: true,
89
- esModuleInterop,
90
- allowSyntheticDefaultImports,
91
- isolatedModules,
92
- noEmitOnError: false,
93
- declaration: false,
94
- sourceMap: false,
73
+ ...options,
74
+ // NO modificar configuraciones del usuario - solo optimizaciones internas del worker que no afectan la validación
75
+ declaration: false, // No necesitamos declaraciones en el worker
76
+ sourceMap: false, // No necesitamos source maps en el worker
95
77
  };
96
78
  };
97
- /**
98
- * Crea un Language Service Host optimizado para validación de tipos eficiente.
99
- */
100
- class TypeScriptLanguageServiceHost {
101
- files = new Map();
102
- compilerOptions;
103
- fileSystemCache = new Map();
104
- constructor(compilerOptions) {
105
- this.compilerOptions = compilerOptions;
106
- }
107
- addFile(fileName, content) {
108
- const existing = this.files.get(fileName);
109
- this.files.set(fileName, {
110
- version: existing ? existing.version + 1 : 1,
111
- content,
112
- });
113
- }
114
- getCompilationSettings() {
115
- return this.compilerOptions;
116
- }
117
- getScriptFileNames() {
118
- return Array.from(this.files.keys());
119
- }
120
- getScriptVersion(fileName) {
121
- const file = this.files.get(fileName);
122
- return file ? file.version.toString() : '0';
123
- }
124
- getScriptSnapshot(fileName) {
125
- const file = this.files.get(fileName);
126
- if (file) {
127
- return typescript.ScriptSnapshot.fromString(file.content);
128
- }
129
- // Cache de sistema de archivos para evitar lecturas repetidas
130
- if (this.fileSystemCache.has(fileName)) {
131
- const cachedContent = this.fileSystemCache.get(fileName);
132
- return cachedContent
133
- ? typescript.ScriptSnapshot.fromString(cachedContent)
134
- : undefined;
135
- }
136
- // Intentar leer el archivo del sistema de archivos solo si es necesario
137
- try {
138
- if (fs.existsSync(fileName)) {
139
- const content = fs.readFileSync(fileName, 'utf-8');
140
- this.fileSystemCache.set(fileName, content);
141
- return typescript.ScriptSnapshot.fromString(content);
142
- }
143
- }
144
- catch {
145
- // Error al leer archivo
146
- }
147
- this.fileSystemCache.set(fileName, undefined);
148
- return undefined;
149
- }
150
- getCurrentDirectory() {
151
- return process.cwd();
152
- }
153
- getDefaultLibFileName(options) {
154
- return typescript.getDefaultLibFilePath(options);
155
- }
156
- fileExists(path) {
157
- if (this.files.has(path))
158
- return true;
159
- if (this.fileSystemCache.has(path)) {
160
- return this.fileSystemCache.get(path) !== undefined;
161
- }
162
- const exists = fs.existsSync(path);
163
- if (!exists)
164
- this.fileSystemCache.set(path, undefined);
165
- return exists;
166
- }
167
- readFile(path) {
168
- const file = this.files.get(path);
169
- if (file)
170
- return file.content;
171
- if (this.fileSystemCache.has(path)) {
172
- return this.fileSystemCache.get(path);
173
- }
174
- try {
175
- if (fs.existsSync(path)) {
176
- const content = fs.readFileSync(path, 'utf-8');
177
- this.fileSystemCache.set(path, content);
178
- return content;
179
- }
180
- }
181
- catch {
182
- // Error al leer archivo
183
- }
184
- this.fileSystemCache.set(path, undefined);
185
- return undefined;
186
- }
187
- getNewLine() {
188
- return typescript.sys.newLine;
189
- }
190
- }
191
- /**
192
- * Realiza validación de tipos optimizada usando TypeScript Language Service.
193
- * @param fileName - Nombre del archivo
194
- * @param content - Contenido del archivo
195
- * @param compilerOptions - Opciones del compilador
196
- * @returns Resultado de la validación de tipos
197
- */
198
- const validateTypesWithLanguageService = (fileName, content, compilerOptions) => {
199
- try {
200
- // Validación temprana: contenido vacío
201
- if (!content.trim()) {
202
- return { diagnostics: [], hasErrors: false };
203
- }
204
- // Crear Language Service Host optimizado
205
- const host = new TypeScriptLanguageServiceHost(compilerOptions);
206
- // Determinar nombre de archivo efectivo
207
- let actualFileName = path.isAbsolute(fileName)
208
- ? fileName
209
- : path.resolve(fileName);
210
- // Para archivos Vue, crear archivo virtual
211
- if (fileName.endsWith('.vue')) {
212
- actualFileName = actualFileName.replace('.vue', '.vue.ts');
213
- host.addFile(actualFileName, content);
214
- // Añadir declaraciones Vue básicas solo si es necesario
215
- const vueTypesPath = path.join(path.dirname(actualFileName), 'vue-types.d.ts');
216
- const vueTypesDeclaration = `
217
- declare global {
218
- function ref<T>(value: T): { value: T };
219
- function reactive<T extends object>(target: T): T;
220
- function computed<T>(getter: () => T): { value: T };
221
- function defineComponent<T>(options: T): T;
222
- function defineProps<T = {}>(): T;
223
- function defineEmits<T = {}>(): T;
224
- function onMounted(fn: () => void): void;
225
- function onUnmounted(fn: () => void): void;
226
- function watch<T>(source: () => T, callback: (newValue: T, oldValue: T) => void): void;
227
- }
228
- export {};`;
229
- host.addFile(vueTypesPath, vueTypesDeclaration);
230
- }
231
- else {
232
- host.addFile(actualFileName, content);
233
- } // Crear Language Service
234
- const languageService = typescript.createLanguageService(host);
235
- // Verificar existencia del archivo
236
- if (!host.fileExists(actualFileName)) {
237
- return { diagnostics: [], hasErrors: false };
238
- }
239
- // Obtener diagnósticos con manejo de errores optimizado
240
- const allDiagnostics = [];
241
- try {
242
- allDiagnostics.push(...languageService.getSyntacticDiagnostics(actualFileName));
243
- allDiagnostics.push(...languageService.getSemanticDiagnostics(actualFileName));
244
- }
245
- catch {
246
- // Ignorar errores de diagnósticos
247
- return { diagnostics: [], hasErrors: false };
248
- } // Filtrado optimizado de diagnósticos
249
- const filteredDiagnostics = allDiagnostics.filter(diag => {
250
- if (diag.category !== typescript.DiagnosticCategory.Error)
251
- return false;
252
- const messageText = typescript.flattenDiagnosticMessageText(diag.messageText, '\n');
253
- // Lista optimizada de patrones a ignorar
254
- const ignorePatterns = [
255
- 'Cannot find module',
256
- 'Could not find source file',
257
- "Parameter '$props' implicitly has an 'any' type",
258
- "Parameter '$setup' implicitly has an 'any' type",
259
- "Parameter '_ctx' implicitly has an 'any' type",
260
- "Parameter '_cache' implicitly has an 'any' type",
261
- ];
262
- return !ignorePatterns.some(pattern => messageText.includes(pattern));
263
- });
264
- return {
265
- diagnostics: filteredDiagnostics,
266
- hasErrors: filteredDiagnostics.length > 0,
267
- };
268
- }
269
- catch (error) {
270
- // Error handling simplificado
271
- return {
272
- diagnostics: [
273
- {
274
- file: undefined,
275
- start: undefined,
276
- length: undefined,
277
- messageText: `Error en validación de tipos: ${error instanceof Error ? error.message : 'Error desconocido'}`,
278
- category: typescript.DiagnosticCategory.Error,
279
- code: 0,
280
- },
281
- ],
282
- hasErrors: true,
283
- };
284
- }
285
- };
286
79
  /**
287
80
  * Valida tipos en archivos Vue antes de la compilación
288
81
  * @param vueContent - Contenido del archivo Vue
@@ -4,6 +4,7 @@ import * as process from 'node:process';
4
4
  import { env } from 'node:process';
5
5
  import * as typescript from 'typescript';
6
6
  import { createUnifiedErrorMessage, parseTypeScriptErrors, } from './typescript-error-parser.js';
7
+ import { validateTypesWithLanguageService } from './typescript-sync-validator.js';
7
8
  import { TypeScriptWorkerPool } from './typescript-worker-pool.js';
8
9
  /**
9
10
  * Cache para la configuración de TypeScript para evitar lecturas repetidas
@@ -15,8 +16,13 @@ let configCache = {};
15
16
  * @returns Opciones del compilador TypeScript
16
17
  */
17
18
  export const loadTypeScriptConfig = (fileName) => {
19
+ // Siempre buscar primero en la raíz del proyecto
20
+ const rootConfigPath = path.resolve(process.cwd(), 'tsconfig.json');
21
+ // Si no existe en la raíz, buscar desde el directorio del archivo
18
22
  const fileDir = path.dirname(fileName);
19
- const configPath = typescript.findConfigFile(fileDir, typescript.sys.fileExists, 'tsconfig.json') || path.resolve(process.cwd(), 'tsconfig.json');
23
+ const configPath = fs.existsSync(rootConfigPath)
24
+ ? rootConfigPath
25
+ : typescript.findConfigFile(fileDir, typescript.sys.fileExists, 'tsconfig.json');
20
26
  // Usar cache si el path no ha cambiado
21
27
  if (configCache.path === configPath && configCache.options) {
22
28
  return configCache.options;
@@ -26,16 +32,12 @@ export const loadTypeScriptConfig = (fileName) => {
26
32
  try {
27
33
  const { config, error: configError } = typescript.readConfigFile(configPath, typescript.sys.readFile);
28
34
  if (!configError) {
29
- const parsedConfig = typescript.parseJsonConfigFileContent(config, typescript.sys, path.dirname(configPath));
30
- compilerOptions = {
31
- ...parsedConfig.options,
32
- // Asegurar opciones básicas necesarias
33
- allowJs: parsedConfig.options.allowJs !== false,
34
- esModuleInterop: parsedConfig.options.esModuleInterop !== false,
35
- allowSyntheticDefaultImports: parsedConfig.options.allowSyntheticDefaultImports !==
36
- false,
37
- skipLibCheck: parsedConfig.options.skipLibCheck !== false,
38
- };
35
+ const parsedConfig = typescript.parseJsonConfigFileContent(config, typescript.sys, path.dirname(configPath)); // Usar exactamente la configuración del tsconfig.json del usuario sin modificaciones
36
+ compilerOptions = parsedConfig.options;
37
+ // DEBUG: Verificar las opciones cargadas
38
+ // console.log(`[DEBUG] Opciones de TypeScript cargadas desde ${configPath}:`);
39
+ // console.log(` noImplicitAny: ${compilerOptions.noImplicitAny}`);
40
+ // console.log(` strict: ${compilerOptions.strict}`);
39
41
  }
40
42
  else {
41
43
  throw new Error(`Error al leer tsconfig.json: ${configError.messageText}`);
@@ -43,255 +45,124 @@ export const loadTypeScriptConfig = (fileName) => {
43
45
  }
44
46
  catch (error) {
45
47
  console.warn(`[loadTypeScriptConfig] Error cargando ${configPath}:`, error);
46
- // Fallback a opciones por defecto
47
- compilerOptions = getDefaultCompilerOptions();
48
+ throw new Error(`No se puede continuar sin un tsconfig.json válido. Error: ${error}`);
48
49
  }
49
50
  }
50
51
  else {
51
- // Opciones por defecto si no se encuentra tsconfig.json
52
- compilerOptions = getDefaultCompilerOptions();
52
+ throw new Error(`No se encontró tsconfig.json en la raíz del proyecto (${rootConfigPath}) ni en el directorio del archivo. ` +
53
+ `El compilador requiere un tsconfig.json para funcionar correctamente.`);
53
54
  }
54
55
  // Guardar en cache
55
56
  configCache = { path: configPath, options: compilerOptions };
56
57
  return compilerOptions;
57
58
  };
58
- /**
59
- * Obtiene las opciones por defecto del compilador TypeScript
60
- */
61
- const getDefaultCompilerOptions = () => ({
62
- target: typescript.ScriptTarget.ES2020,
63
- module: typescript.ModuleKind.ES2020,
64
- lib: ['es2020', 'dom', 'dom.iterable'],
65
- strict: false,
66
- skipLibCheck: true,
67
- allowJs: true,
68
- esModuleInterop: true,
69
- allowSyntheticDefaultImports: true,
70
- isolatedModules: true,
71
- });
72
59
  /**
73
60
  * Crea una versión optimizada y serializable de las opciones del compilador typescript.
74
61
  * @param options - Opciones originales del compilador
75
62
  * @returns Opciones serializables seguras para workers
76
63
  */
77
64
  const createSerializableCompilerOptions = (options) => {
78
- // Usar las opciones del tsconfig.json pero con optimizaciones para el worker
79
- const { target = typescript.ScriptTarget.ES2020, module = typescript.ModuleKind.ES2020, lib = ['es2020', 'dom', 'dom.iterable'], allowJs = true, jsx, strict = false, skipLibCheck = true, esModuleInterop = true, allowSyntheticDefaultImports = true, isolatedModules = true, } = options;
80
- return {
81
- target,
82
- module,
83
- lib: Array.isArray(lib) ? lib : ['es2020', 'dom', 'dom.iterable'],
84
- allowJs,
85
- jsx,
86
- strict,
87
- skipLibCheck,
88
- skipDefaultLibCheck: true,
89
- esModuleInterop,
90
- allowSyntheticDefaultImports,
91
- isolatedModules,
92
- noEmitOnError: false,
93
- declaration: false,
94
- sourceMap: false,
95
- };
65
+ // Respetar exactamente las opciones del tsconfig.json del usuario // Respetar completamente la configuración del usuario del tsconfig.json
66
+ const result = { ...options };
67
+ // NO modificar ninguna opción del usuario - usar configuración exacta del tsconfig.json
68
+ return result;
96
69
  };
97
70
  /**
98
71
  * Crea un Language Service Host optimizado para validación de tipos eficiente.
99
72
  */
100
- class TypeScriptLanguageServiceHost {
101
- files = new Map();
102
- compilerOptions;
103
- fileSystemCache = new Map();
104
- constructor(compilerOptions) {
105
- this.compilerOptions = compilerOptions;
73
+ /**
74
+ * Valida tipos en archivos Vue antes de la compilación con soporte mejorado
75
+ * @param vueContent - Contenido del archivo Vue
76
+ * @param fileName - Nombre del archivo Vue
77
+ * @param options - Opciones adicionales para la validación
78
+ * @returns Resultado de la validación de tipos
79
+ */
80
+ export const validateVueTypes = (vueContent, fileName, options) => {
81
+ // Extraer contenido del script de Vue
82
+ let scriptContent = '';
83
+ if (fileName.endsWith('.vue')) {
84
+ // Extraer contenido entre <script> y </script>
85
+ const scriptMatch = vueContent.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
86
+ if (scriptMatch && scriptMatch[1]) {
87
+ scriptContent = scriptMatch[1].trim();
88
+ }
89
+ else {
90
+ // Si no hay script, no hay nada que validar
91
+ return { diagnostics: [], hasErrors: false };
92
+ }
106
93
  }
107
- addFile(fileName, content) {
108
- const existing = this.files.get(fileName);
109
- this.files.set(fileName, {
110
- version: existing ? existing.version + 1 : 1,
111
- content,
112
- });
94
+ else {
95
+ // Para archivos .ts/.js normales, usar todo el contenido
96
+ scriptContent = vueContent;
113
97
  }
114
- getCompilationSettings() {
115
- return this.compilerOptions;
98
+ // Si el script está vacío, no validar
99
+ if (!scriptContent.trim()) {
100
+ return { diagnostics: [], hasErrors: false };
116
101
  }
117
- getScriptFileNames() {
118
- return Array.from(this.files.keys());
102
+ // Cargar la configuración del usuario como base
103
+ const userConfig = loadTypeScriptConfig(fileName);
104
+ // Crear opciones del compilador respetando la configuración del usuario
105
+ let compilerOptions;
106
+ if (options?.compilerOptions) {
107
+ // Si se proporcionaron opciones explícitas, usarlas como base
108
+ compilerOptions = { ...options.compilerOptions };
119
109
  }
120
- getScriptVersion(fileName) {
121
- const file = this.files.get(fileName);
122
- return file ? file.version.toString() : '0';
110
+ else {
111
+ // Usar la configuración del usuario como base
112
+ compilerOptions = { ...userConfig };
123
113
  }
124
- getScriptSnapshot(fileName) {
125
- const file = this.files.get(fileName);
126
- if (file) {
127
- return typescript.ScriptSnapshot.fromString(file.content);
114
+ // Solo forzar las opciones ABSOLUTAMENTE necesarias para Vue
115
+ // Estas opciones se fuerzan porque son técnicamente requeridas para el funcionamiento correcto
116
+ if (fileName.endsWith('.vue')) {
117
+ // JSX: Necesario para que funcione el template compilation de Vue
118
+ compilerOptions.jsx = typescript.JsxEmit.Preserve;
119
+ // ModuleResolution: Necesario para resolver módulos Vue correctamente
120
+ if (!compilerOptions.moduleResolution) {
121
+ compilerOptions.moduleResolution =
122
+ typescript.ModuleResolutionKind.NodeJs;
128
123
  }
129
- // Cache de sistema de archivos para evitar lecturas repetidas
130
- if (this.fileSystemCache.has(fileName)) {
131
- const cachedContent = this.fileSystemCache.get(fileName);
132
- return cachedContent
133
- ? typescript.ScriptSnapshot.fromString(cachedContent)
134
- : undefined;
135
- }
136
- // Intentar leer el archivo del sistema de archivos solo si es necesario
137
- try {
138
- if (fs.existsSync(fileName)) {
139
- const content = fs.readFileSync(fileName, 'utf-8');
140
- this.fileSystemCache.set(fileName, content);
141
- return typescript.ScriptSnapshot.fromString(content);
142
- }
124
+ // Lib: Asegurar que DOM esté disponible para archivos Vue, pero respetar otras libs del usuario
125
+ const currentLibs = compilerOptions.lib || userConfig.lib || ['ES2020'];
126
+ const hasDOM = currentLibs.some(lib => typeof lib === 'string' &&
127
+ (lib.toLowerCase().includes('dom') ||
128
+ lib.toLowerCase() === 'dom'));
129
+ if (!hasDOM) {
130
+ compilerOptions.lib = [...currentLibs, 'DOM', 'DOM.Iterable'];
143
131
  }
144
- catch {
145
- // Error al leer archivo
132
+ // Types: Agregar 'vue' si no está presente, pero mantener otros types del usuario
133
+ const currentTypes = compilerOptions.types || userConfig.types || [];
134
+ if (!currentTypes.includes('vue')) {
135
+ compilerOptions.types = [...currentTypes, 'vue'];
146
136
  }
147
- this.fileSystemCache.set(fileName, undefined);
148
- return undefined;
149
137
  }
150
- getCurrentDirectory() {
151
- return process.cwd();
138
+ // Configuraciones que mejoran la detección de errores pero respetan preferencias del usuario
139
+ // Solo se aplican si el usuario no las ha configurado explícitamente
140
+ if (compilerOptions.skipLibCheck === undefined) {
141
+ compilerOptions.skipLibCheck = true; // Para evitar errores en librerías externas
152
142
  }
153
- getDefaultLibFileName(options) {
154
- return typescript.getDefaultLibFilePath(options);
155
- }
156
- fileExists(path) {
157
- if (this.files.has(path))
158
- return true;
159
- if (this.fileSystemCache.has(path)) {
160
- return this.fileSystemCache.get(path) !== undefined;
161
- }
162
- const exists = fs.existsSync(path);
163
- if (!exists)
164
- this.fileSystemCache.set(path, undefined);
165
- return exists;
166
- }
167
- readFile(path) {
168
- const file = this.files.get(path);
169
- if (file)
170
- return file.content;
171
- if (this.fileSystemCache.has(path)) {
172
- return this.fileSystemCache.get(path);
173
- }
174
- try {
175
- if (fs.existsSync(path)) {
176
- const content = fs.readFileSync(path, 'utf-8');
177
- this.fileSystemCache.set(path, content);
178
- return content;
179
- }
143
+ // Aplicar strictMode solo si el usuario no ha configurado estas opciones individualmente
144
+ if (options?.strictMode !== undefined) {
145
+ if (compilerOptions.noImplicitReturns === undefined) {
146
+ compilerOptions.noImplicitReturns = options.strictMode;
180
147
  }
181
- catch {
182
- // Error al leer archivo
148
+ if (compilerOptions.noImplicitThis === undefined) {
149
+ compilerOptions.noImplicitThis = options.strictMode;
183
150
  }
184
- this.fileSystemCache.set(path, undefined);
185
- return undefined;
186
- }
187
- getNewLine() {
188
- return typescript.sys.newLine;
189
- }
190
- }
191
- /**
192
- * Realiza validación de tipos optimizada usando TypeScript Language Service.
193
- * @param fileName - Nombre del archivo
194
- * @param content - Contenido del archivo
195
- * @param compilerOptions - Opciones del compilador
196
- * @returns Resultado de la validación de tipos
197
- */
198
- const validateTypesWithLanguageService = (fileName, content, compilerOptions) => {
199
- try {
200
- // Validación temprana: contenido vacío
201
- if (!content.trim()) {
202
- return { diagnostics: [], hasErrors: false };
151
+ if (compilerOptions.strictNullChecks === undefined) {
152
+ compilerOptions.strictNullChecks = options.strictMode;
203
153
  }
204
- // Crear Language Service Host optimizado
205
- const host = new TypeScriptLanguageServiceHost(compilerOptions);
206
- // Determinar nombre de archivo efectivo
207
- let actualFileName = path.isAbsolute(fileName)
208
- ? fileName
209
- : path.resolve(fileName);
210
- // Para archivos Vue, crear archivo virtual
211
- if (fileName.endsWith('.vue')) {
212
- actualFileName = actualFileName.replace('.vue', '.vue.ts');
213
- host.addFile(actualFileName, content);
214
- // Añadir declaraciones Vue básicas solo si es necesario
215
- const vueTypesPath = path.join(path.dirname(actualFileName), 'vue-types.d.ts');
216
- const vueTypesDeclaration = `
217
- declare global {
218
- function ref<T>(value: T): { value: T };
219
- function reactive<T extends object>(target: T): T;
220
- function computed<T>(getter: () => T): { value: T };
221
- function defineComponent<T>(options: T): T;
222
- function defineProps<T = {}>(): T;
223
- function defineEmits<T = {}>(): T;
224
- function onMounted(fn: () => void): void;
225
- function onUnmounted(fn: () => void): void;
226
- function watch<T>(source: () => T, callback: (newValue: T, oldValue: T) => void): void;
227
- }
228
- export {};`;
229
- host.addFile(vueTypesPath, vueTypesDeclaration);
154
+ if (compilerOptions.strictFunctionTypes === undefined) {
155
+ compilerOptions.strictFunctionTypes = options.strictMode;
230
156
  }
231
- else {
232
- host.addFile(actualFileName, content);
233
- } // Crear Language Service
234
- const languageService = typescript.createLanguageService(host);
235
- // Verificar existencia del archivo
236
- if (!host.fileExists(actualFileName)) {
237
- return { diagnostics: [], hasErrors: false };
157
+ if (compilerOptions.exactOptionalPropertyTypes === undefined) {
158
+ compilerOptions.exactOptionalPropertyTypes = false; // Menos estricto por defecto
238
159
  }
239
- // Obtener diagnósticos con manejo de errores optimizado
240
- const allDiagnostics = [];
241
- try {
242
- allDiagnostics.push(...languageService.getSyntacticDiagnostics(actualFileName));
243
- allDiagnostics.push(...languageService.getSemanticDiagnostics(actualFileName));
160
+ if (compilerOptions.noFallthroughCasesInSwitch === undefined) {
161
+ compilerOptions.noFallthroughCasesInSwitch = options.strictMode;
244
162
  }
245
- catch {
246
- // Ignorar errores de diagnósticos
247
- return { diagnostics: [], hasErrors: false };
248
- } // Filtrado optimizado de diagnósticos
249
- const filteredDiagnostics = allDiagnostics.filter(diag => {
250
- if (diag.category !== typescript.DiagnosticCategory.Error)
251
- return false;
252
- const messageText = typescript.flattenDiagnosticMessageText(diag.messageText, '\n');
253
- // Lista optimizada de patrones a ignorar
254
- const ignorePatterns = [
255
- 'Cannot find module',
256
- 'Could not find source file',
257
- "Parameter '$props' implicitly has an 'any' type",
258
- "Parameter '$setup' implicitly has an 'any' type",
259
- "Parameter '_ctx' implicitly has an 'any' type",
260
- "Parameter '_cache' implicitly has an 'any' type",
261
- ];
262
- return !ignorePatterns.some(pattern => messageText.includes(pattern));
263
- });
264
- return {
265
- diagnostics: filteredDiagnostics,
266
- hasErrors: filteredDiagnostics.length > 0,
267
- };
268
- }
269
- catch (error) {
270
- // Error handling simplificado
271
- return {
272
- diagnostics: [
273
- {
274
- file: undefined,
275
- start: undefined,
276
- length: undefined,
277
- messageText: `Error en validación de tipos: ${error instanceof Error ? error.message : 'Error desconocido'}`,
278
- category: typescript.DiagnosticCategory.Error,
279
- code: 0,
280
- },
281
- ],
282
- hasErrors: true,
283
- };
284
163
  }
285
- };
286
- /**
287
- * Valida tipos en archivos Vue antes de la compilación
288
- * @param vueContent - Contenido del archivo Vue
289
- * @param fileName - Nombre del archivo Vue
290
- * @returns Resultado de la validación de tipos
291
- */
292
- export const validateVueTypes = (vueContent, fileName) => {
293
- const compilerOptions = loadTypeScriptConfig(fileName);
294
- return validateTypesWithLanguageService(fileName, vueContent, compilerOptions);
164
+ return validateTypesWithLanguageService(fileName, scriptContent, // Usar solo el contenido del script
165
+ compilerOptions);
295
166
  };
296
167
  /**
297
168
  * Precompila el código TypeScript con pipeline optimizado para máxima performance.
@@ -340,7 +211,9 @@ export const preCompileTS = async (data, fileName) => {
340
211
  };
341
212
  }
342
213
  } // PASO 2: Type checking opcional (solo si está habilitado)
214
+ // console.log(`[DEBUG] env.typeCheck: ${env.typeCheck}`);
343
215
  if (env.typeCheck === 'true') {
216
+ // console.log(`[DEBUG] Iniciando verificación de tipos para: ${fileName}`);
344
217
  try {
345
218
  const workerPool = TypeScriptWorkerPool.getInstance();
346
219
  const serializableOptions = createSerializableCompilerOptions(compilerOptions);