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
package/dist/main.js
CHANGED
|
@@ -66,7 +66,8 @@ async function main() {
|
|
|
66
66
|
const chalkInstance = await loadChalk();
|
|
67
67
|
let yargInstance = yargsInstance(hideBinFn(globalProcess.argv))
|
|
68
68
|
.scriptName('versa')
|
|
69
|
-
.usage(chalkInstance.blue('VersaCompiler') +
|
|
69
|
+
.usage(chalkInstance.blue('VersaCompiler') +
|
|
70
|
+
' - Compilador de archivos Vue/TS/JS')
|
|
70
71
|
.option('init', {
|
|
71
72
|
type: 'boolean',
|
|
72
73
|
description: 'Inicializar la configuración',
|
|
@@ -565,11 +565,17 @@ export async function browserSyncServer() {
|
|
|
565
565
|
process.exit(1);
|
|
566
566
|
}
|
|
567
567
|
}
|
|
568
|
-
export async function emitirCambios(bs, action, filePath) {
|
|
568
|
+
export async function emitirCambios(bs, action, filePath, payload = {}) {
|
|
569
569
|
// ✨ OPTIMIZACIÓN: Emitir PRIMERO (crítico), logging DESPUÉS (no crítico)
|
|
570
570
|
const normalizedPath = path.normalize(filePath).replace(/\\/g, '/');
|
|
571
571
|
const nameFile = path.basename(normalizedPath, path.extname(normalizedPath));
|
|
572
|
-
bs.sockets.emit(action, {
|
|
572
|
+
bs.sockets.emit(action, {
|
|
573
|
+
action,
|
|
574
|
+
filePath,
|
|
575
|
+
normalizedPath,
|
|
576
|
+
nameFile,
|
|
577
|
+
...payload,
|
|
578
|
+
});
|
|
573
579
|
// Logging asíncrono para no bloquear la emisión
|
|
574
580
|
setImmediate(async () => {
|
|
575
581
|
const chalkInstance = await loadChalk();
|
|
@@ -4,7 +4,7 @@ import * as process from 'node:process';
|
|
|
4
4
|
const { env } = process;
|
|
5
5
|
import * as chokidar from 'chokidar';
|
|
6
6
|
import { minimatch } from 'minimatch';
|
|
7
|
-
import { clearCompilationState, getOutputPath, initCompile, normalizeRuta } from '../compiler/compile.js';
|
|
7
|
+
import { clearCompilationState, getOutputPath, getPipelineModuleGraph, initCompile, normalizeRuta, runPipelineHotUpdate, } from '../compiler/compile.js';
|
|
8
8
|
import { promptUser } from '../utils/promptUser.js';
|
|
9
9
|
import { emitirCambios } from './browserSync.js';
|
|
10
10
|
import { logger } from './logger.js';
|
|
@@ -147,13 +147,32 @@ class WatchDebouncer {
|
|
|
147
147
|
*/
|
|
148
148
|
async processCompilableFiles(compilableFiles) {
|
|
149
149
|
const chalkInstance = await loadChalk();
|
|
150
|
+
const graph = getPipelineModuleGraph();
|
|
150
151
|
// Procesar en batches para evitar sobrecarga
|
|
151
152
|
for (let i = 0; i < compilableFiles.length; i += this.BATCH_SIZE) {
|
|
152
153
|
const batch = compilableFiles.slice(i, i + this.BATCH_SIZE);
|
|
153
154
|
if (batch.length > 1) {
|
|
154
155
|
logger.info(chalkInstance.cyan(`📦 Procesando batch de ${batch.length} archivos compilables (${i + 1}-${Math.min(i + this.BATCH_SIZE, compilableFiles.length)} de ${compilableFiles.length})`));
|
|
155
156
|
}
|
|
156
|
-
const
|
|
157
|
+
const expandedChanges = new Map();
|
|
158
|
+
for (const change of batch) {
|
|
159
|
+
expandedChanges.set(change.filePath, change);
|
|
160
|
+
if (graph) {
|
|
161
|
+
const invalidated = graph.invalidate(change.filePath);
|
|
162
|
+
for (const invalidatedPath of invalidated) {
|
|
163
|
+
if (expandedChanges.has(invalidatedPath))
|
|
164
|
+
continue;
|
|
165
|
+
expandedChanges.set(invalidatedPath, {
|
|
166
|
+
filePath: invalidatedPath,
|
|
167
|
+
action: 'change',
|
|
168
|
+
timestamp: Date.now(),
|
|
169
|
+
extensionAction: 'reloadFull',
|
|
170
|
+
isAdditionalFile: false,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const promises = Array.from(expandedChanges.values()).map(change => this.compileFile(change));
|
|
157
176
|
await Promise.allSettled(promises);
|
|
158
177
|
}
|
|
159
178
|
if (compilableFiles.length > 1) {
|
|
@@ -177,12 +196,37 @@ class WatchDebouncer {
|
|
|
177
196
|
*/
|
|
178
197
|
async compileFile(change) {
|
|
179
198
|
try {
|
|
199
|
+
let pluginHmrReload = 'none';
|
|
200
|
+
if (change.action !== 'unlink') {
|
|
201
|
+
const hotUpdate = await runPipelineHotUpdate(change.filePath, change.action);
|
|
202
|
+
pluginHmrReload = hotUpdate.reload || 'none';
|
|
203
|
+
}
|
|
180
204
|
const result = await initCompile(change.filePath, true, 'watch');
|
|
181
205
|
if (result.success) {
|
|
182
206
|
let accion = result.action || change.extensionAction;
|
|
183
207
|
accion =
|
|
184
208
|
accion === 'extension' ? change.extensionAction : accion;
|
|
185
|
-
|
|
209
|
+
let payload = {};
|
|
210
|
+
if (accion === 'HRMHelper') {
|
|
211
|
+
if (pluginHmrReload === 'full') {
|
|
212
|
+
accion = 'reloadFull';
|
|
213
|
+
}
|
|
214
|
+
const graph = getPipelineModuleGraph();
|
|
215
|
+
const node = graph?.getNode(change.filePath);
|
|
216
|
+
const importers = node ? Array.from(node.importers) : [];
|
|
217
|
+
const strategy = importers.length > 0 ? 'propagate' : 'full-reload';
|
|
218
|
+
if (pluginHmrReload === 'module') {
|
|
219
|
+
payload.strategy = 'propagate';
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
payload.strategy = strategy;
|
|
223
|
+
}
|
|
224
|
+
payload = {
|
|
225
|
+
importers,
|
|
226
|
+
...payload,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
emitirCambios(this.browserSyncInstance, accion || 'reloadFull', result.output, payload);
|
|
186
230
|
}
|
|
187
231
|
}
|
|
188
232
|
catch (error) {
|
|
@@ -355,9 +399,7 @@ export async function initChokidar(bs) {
|
|
|
355
399
|
// ✨ OPTIMIZACIÓN: Pre-cargar módulos críticos al iniciar el watcher
|
|
356
400
|
watcher.on('ready', async () => {
|
|
357
401
|
const chalkInstance = await loadChalk();
|
|
358
|
-
logger.info(chalkInstance.green(`👀 : Listo para observar \n${fileWatch
|
|
359
|
-
.map((item) => `${item}`)
|
|
360
|
-
.join('\n')}\n`));
|
|
402
|
+
logger.info(chalkInstance.green(`👀 : Listo para observar \n${fileWatch.map((item) => `${item}`).join('\n')}\n`));
|
|
361
403
|
// Pre-cargar módulos críticos para primera compilación más rápida
|
|
362
404
|
setImmediate(async () => {
|
|
363
405
|
try {
|
|
@@ -25,7 +25,7 @@ export function validatePath(pathStr) {
|
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
27
|
// Rechazar rutas absolutas de Windows (válido en cualquier plataforma)
|
|
28
|
-
if (/^[A-Za-z]:[
|
|
28
|
+
if (/^[A-Za-z]:[/\\]/.test(pathStr)) {
|
|
29
29
|
logger.error(`Ruta absoluta de Windows no permitida: ${pathStr}`);
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
@@ -238,6 +238,80 @@ function safeJsonStringify(obj, fallback = 'false') {
|
|
|
238
238
|
return fallback;
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
+
function normalizeAliasKey(key) {
|
|
242
|
+
if (key.includes('*'))
|
|
243
|
+
return key;
|
|
244
|
+
if (key.endsWith('/'))
|
|
245
|
+
return `${key}*`;
|
|
246
|
+
return `${key}/*`;
|
|
247
|
+
}
|
|
248
|
+
function normalizeAliasValue(value) {
|
|
249
|
+
if (value.includes('*'))
|
|
250
|
+
return value;
|
|
251
|
+
if (value.endsWith('/'))
|
|
252
|
+
return `${value}*`;
|
|
253
|
+
return `${value}/*`;
|
|
254
|
+
}
|
|
255
|
+
function normalizeAlias(alias) {
|
|
256
|
+
if (!alias)
|
|
257
|
+
return {};
|
|
258
|
+
const result = {};
|
|
259
|
+
if (Array.isArray(alias)) {
|
|
260
|
+
for (const entry of alias) {
|
|
261
|
+
if (!entry || typeof entry.find !== 'string')
|
|
262
|
+
continue;
|
|
263
|
+
if (typeof entry.replacement !== 'string')
|
|
264
|
+
continue;
|
|
265
|
+
const key = normalizeAliasKey(entry.find);
|
|
266
|
+
const value = normalizeAliasValue(entry.replacement);
|
|
267
|
+
result[key] = [value];
|
|
268
|
+
}
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
for (const [key, value] of Object.entries(alias)) {
|
|
272
|
+
const normalizedKey = normalizeAliasKey(key);
|
|
273
|
+
if (Array.isArray(value)) {
|
|
274
|
+
result[normalizedKey] = value
|
|
275
|
+
.filter(v => typeof v === 'string')
|
|
276
|
+
.map(v => normalizeAliasValue(v));
|
|
277
|
+
}
|
|
278
|
+
else if (typeof value === 'string') {
|
|
279
|
+
result[normalizedKey] = [normalizeAliasValue(value)];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
function normalizeConfig(input) {
|
|
285
|
+
if (input?.compilerOptions) {
|
|
286
|
+
return input;
|
|
287
|
+
}
|
|
288
|
+
const viteConfig = input;
|
|
289
|
+
const aliases = normalizeAlias(viteConfig?.resolve?.alias);
|
|
290
|
+
return {
|
|
291
|
+
tsconfig: viteConfig?.tsconfig,
|
|
292
|
+
compilerOptions: {
|
|
293
|
+
sourceRoot: viteConfig?.root || './src',
|
|
294
|
+
outDir: viteConfig?.build?.outDir || './dist',
|
|
295
|
+
pathsAlias: aliases,
|
|
296
|
+
},
|
|
297
|
+
plugins: viteConfig?.plugins,
|
|
298
|
+
proxyConfig: {
|
|
299
|
+
proxyUrl: viteConfig?.server?.proxyUrl || '',
|
|
300
|
+
assetsOmit: viteConfig?.server?.assetsOmit ?? false,
|
|
301
|
+
},
|
|
302
|
+
aditionalWatch: viteConfig?.watch?.additional ||
|
|
303
|
+
viteConfig?.server?.watch?.additional ||
|
|
304
|
+
[],
|
|
305
|
+
tailwindConfig: viteConfig?.tailwindConfig,
|
|
306
|
+
linter: viteConfig?.linter,
|
|
307
|
+
bundlers: viteConfig?.build?.bundlers,
|
|
308
|
+
typeCheckOptions: viteConfig?.typeCheckOptions,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
let loadedConfig = null;
|
|
312
|
+
export function getLoadedConfig() {
|
|
313
|
+
return loadedConfig;
|
|
314
|
+
}
|
|
241
315
|
/**
|
|
242
316
|
* Wrapper para el import dinámico que permite mejor testing
|
|
243
317
|
*/
|
|
@@ -272,7 +346,8 @@ export async function readConfig() {
|
|
|
272
346
|
if (!data) {
|
|
273
347
|
throw new Error('No se pudo leer el archivo de configuración.');
|
|
274
348
|
}
|
|
275
|
-
const
|
|
349
|
+
const rawConfig = data.default || data;
|
|
350
|
+
const tsConfig = normalizeConfig(rawConfig);
|
|
276
351
|
// Validar tamaño de configuración
|
|
277
352
|
if (!validateConfigSize(tsConfig)) {
|
|
278
353
|
throw new Error('Configuración demasiado grande o contiene referencias circulares.');
|
|
@@ -323,6 +398,7 @@ export async function readConfig() {
|
|
|
323
398
|
if (!tsConfig.compilerOptions.sourceRoot) {
|
|
324
399
|
env.tsConfig = safeJsonStringify(tsConfig, '{}');
|
|
325
400
|
}
|
|
401
|
+
loadedConfig = tsConfig;
|
|
326
402
|
logger.info('✅ Configuration loaded and validated successfully');
|
|
327
403
|
return true;
|
|
328
404
|
}
|
|
@@ -347,58 +423,57 @@ export async function initConfig() {
|
|
|
347
423
|
logger.warn(`🚩 El archivo de configuración '${env.PATH_CONFIG_FILE}' ya existe.`);
|
|
348
424
|
return true;
|
|
349
425
|
}
|
|
350
|
-
const configContent =
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
outDir: './dist',
|
|
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
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
};
|
|
426
|
+
const configContent = `import { defineConfig } from 'versacompiler/config';
|
|
427
|
+
|
|
428
|
+
export default defineConfig({
|
|
429
|
+
root: './src',
|
|
430
|
+
build: {
|
|
431
|
+
outDir: './dist',
|
|
432
|
+
bundlers: [
|
|
433
|
+
{
|
|
434
|
+
name: 'appLoader',
|
|
435
|
+
fileInput: './public/module/appLoader.js',
|
|
436
|
+
fileOutput: './public/module/appLoader.prod.js',
|
|
437
|
+
},
|
|
438
|
+
],
|
|
439
|
+
},
|
|
440
|
+
resolve: {
|
|
441
|
+
alias: {
|
|
442
|
+
'/dist': 'src',
|
|
443
|
+
'/dist/public': 'public',
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
server: {
|
|
447
|
+
proxyUrl: '',
|
|
448
|
+
assetsOmit: true,
|
|
449
|
+
watch: {
|
|
450
|
+
additional: ['./app/templates/**/*.twig', './app/templates/**/*.html'],
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
tsconfig: './tsconfig.json',
|
|
454
|
+
tailwindConfig: {
|
|
455
|
+
bin: './node_modules/.bin/tailwindcss',
|
|
456
|
+
input: './src/css/input.css',
|
|
457
|
+
output: './public/css/output.css',
|
|
458
|
+
},
|
|
459
|
+
linter: [
|
|
460
|
+
{
|
|
461
|
+
name: 'eslint',
|
|
462
|
+
bin: './node_modules/.bin/eslint',
|
|
463
|
+
configFile: './.eslintrc.json',
|
|
464
|
+
fix: false,
|
|
465
|
+
paths: ['src/'],
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
name: 'oxlint',
|
|
469
|
+
bin: './node_modules/.bin/oxlint',
|
|
470
|
+
configFile: './.oxlintrc.json',
|
|
471
|
+
fix: false,
|
|
472
|
+
paths: ['src/'],
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
plugins: [],
|
|
476
|
+
});
|
|
402
477
|
`;
|
|
403
478
|
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
404
479
|
logger.info(`🚩 Archivo de configuración '${env.PATH_CONFIG_FILE}' creado correctamente.`);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// Opción con librería '
|
|
1
|
+
// Opción con librería 'resolve' (npm install resolve)
|
|
2
2
|
import fs, { readFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, join, relative } from 'node:path';
|
|
4
4
|
import { cwd, env } from 'node:process';
|
|
5
|
-
// import pkg from '
|
|
6
|
-
// import resolve from '
|
|
5
|
+
// import pkg from 'enhanced-resolve';
|
|
6
|
+
// import resolve from 'resolve';
|
|
7
7
|
import { logger } from '../servicios/logger.js';
|
|
8
8
|
import { EXCLUDED_MODULES } from './excluded-modules.js';
|
|
9
9
|
class PackageJsonCache {
|
|
@@ -72,7 +72,7 @@ const packageJsonCache = PackageJsonCache.getInstance();
|
|
|
72
72
|
// return null;
|
|
73
73
|
// }
|
|
74
74
|
// }
|
|
75
|
-
// Opción con '
|
|
75
|
+
// Opción con 'enhanced-resolve' (webpack's resolver)
|
|
76
76
|
// npm install enhanced-resolve
|
|
77
77
|
// const { ResolverFactory } = pkg;
|
|
78
78
|
// const resolver = ResolverFactory.createResolver({
|
|
@@ -350,26 +350,7 @@ function simpleESMResolver(moduleName) {
|
|
|
350
350
|
entryPoint = dotExport;
|
|
351
351
|
}
|
|
352
352
|
else if (typeof dotExport === 'object') {
|
|
353
|
-
|
|
354
|
-
// Buscar específicamente patrones esm-browser primero
|
|
355
|
-
const exportKeys = Object.keys(dotExport);
|
|
356
|
-
const esmBrowserKey = exportKeys.find(key => key.includes('browser') &&
|
|
357
|
-
(key.includes('esm') || key.includes('module')));
|
|
358
|
-
if (esmBrowserKey &&
|
|
359
|
-
typeof dotExport[esmBrowserKey] === 'string') {
|
|
360
|
-
entryPoint = dotExport[esmBrowserKey];
|
|
361
|
-
}
|
|
362
|
-
else {
|
|
363
|
-
// Priorizar import > browser > default
|
|
364
|
-
entryPoint =
|
|
365
|
-
(typeof dotExport.import === 'string'
|
|
366
|
-
? dotExport.import
|
|
367
|
-
: null) ||
|
|
368
|
-
dotExport.browser ||
|
|
369
|
-
(typeof dotExport.default === 'string'
|
|
370
|
-
? dotExport.default
|
|
371
|
-
: null);
|
|
372
|
-
}
|
|
353
|
+
entryPoint = resolveExportValue(dotExport);
|
|
373
354
|
}
|
|
374
355
|
}
|
|
375
356
|
}
|
|
@@ -489,6 +470,64 @@ function getNodeModulesRelativePath(fullPath, _fromFile) {
|
|
|
489
470
|
}
|
|
490
471
|
return rel;
|
|
491
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Parses a module specifier into packageName and subPath.
|
|
475
|
+
* Handles scoped packages correctly.
|
|
476
|
+
* Examples:
|
|
477
|
+
* '@vueuse/core' → { packageName: '@vueuse/core', subPath: '' }
|
|
478
|
+
* '@vueuse/core/sub' → { packageName: '@vueuse/core', subPath: 'sub' }
|
|
479
|
+
* 'vue/dist/x' → { packageName: 'vue', subPath: 'dist/x' }
|
|
480
|
+
* 'vue' → { packageName: 'vue', subPath: '' }
|
|
481
|
+
*/
|
|
482
|
+
export function parseModuleSpecifier(moduleName) {
|
|
483
|
+
if (moduleName.startsWith('@')) {
|
|
484
|
+
const parts = moduleName.split('/');
|
|
485
|
+
if (parts.length < 2 || !parts[1]) {
|
|
486
|
+
return { packageName: moduleName, subPath: '' };
|
|
487
|
+
}
|
|
488
|
+
const packageName = `${parts[0]}/${parts[1]}`;
|
|
489
|
+
const subPath = parts.slice(2).join('/');
|
|
490
|
+
return { packageName, subPath };
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
const slashIdx = moduleName.indexOf('/');
|
|
494
|
+
if (slashIdx === -1) {
|
|
495
|
+
return { packageName: moduleName, subPath: '' };
|
|
496
|
+
}
|
|
497
|
+
return {
|
|
498
|
+
packageName: moduleName.slice(0, slashIdx),
|
|
499
|
+
subPath: moduleName.slice(slashIdx + 1),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Recursively resolves a conditional export value.
|
|
505
|
+
* Priority: import > browser > module > default
|
|
506
|
+
* Handles nested objects up to a depth limit.
|
|
507
|
+
*/
|
|
508
|
+
export function resolveExportValue(exportVal, depth = 0) {
|
|
509
|
+
if (depth > 5)
|
|
510
|
+
return null;
|
|
511
|
+
if (typeof exportVal === 'string')
|
|
512
|
+
return exportVal;
|
|
513
|
+
if (typeof exportVal === 'object' && exportVal !== null) {
|
|
514
|
+
const obj = exportVal;
|
|
515
|
+
for (const key of [
|
|
516
|
+
'import',
|
|
517
|
+
'browser',
|
|
518
|
+
'module',
|
|
519
|
+
'default',
|
|
520
|
+
'require',
|
|
521
|
+
]) {
|
|
522
|
+
if (obj[key] !== undefined) {
|
|
523
|
+
const resolved = resolveExportValue(obj[key], depth + 1);
|
|
524
|
+
if (resolved)
|
|
525
|
+
return resolved;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return null;
|
|
530
|
+
}
|
|
492
531
|
export function getModulePath(moduleName, fromFile) {
|
|
493
532
|
// Verificar si el módulo está en la lista de excluidos
|
|
494
533
|
if (EXCLUDED_MODULES.has(moduleName)) {
|
|
@@ -501,14 +540,15 @@ export function getModuleSubPath(moduleName, fromFile) {
|
|
|
501
540
|
// Verificar si el módulo está en la lista de excluidos
|
|
502
541
|
if (EXCLUDED_MODULES.has(moduleName)) {
|
|
503
542
|
return null; // Retornar null para mantener la importación original
|
|
504
|
-
}
|
|
543
|
+
}
|
|
544
|
+
// Usar parseModuleSpecifier para manejar correctamente paquetes con scope
|
|
545
|
+
const { packageName, subPath } = parseModuleSpecifier(moduleName);
|
|
546
|
+
// Si no hay subPath, delegar al resolver normal
|
|
547
|
+
if (!subPath) {
|
|
548
|
+
return getModulePath(moduleName, fromFile);
|
|
549
|
+
}
|
|
550
|
+
// Es un subpath: resolver con el packageName correcto
|
|
505
551
|
if (moduleName.includes('/')) {
|
|
506
|
-
const [packageName, ...subPathParts] = moduleName.split('/');
|
|
507
|
-
const subPath = subPathParts.join('/');
|
|
508
|
-
// Verificar que packageName no esté vacío
|
|
509
|
-
if (!packageName) {
|
|
510
|
-
return null;
|
|
511
|
-
}
|
|
512
552
|
try {
|
|
513
553
|
const nodeModulesPath = join(cwd(), 'node_modules', packageName);
|
|
514
554
|
const packagePath = join(nodeModulesPath, 'package.json');
|
|
@@ -525,15 +565,9 @@ export function getModuleSubPath(moduleName, fromFile) {
|
|
|
525
565
|
const exportKey = `./${subPath}`;
|
|
526
566
|
const exportPath = packageJson.exports[exportKey];
|
|
527
567
|
if (exportPath) {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
else if (typeof exportPath === 'object') {
|
|
532
|
-
// Priorizar import > default para ESM
|
|
533
|
-
const importPath = exportPath.import || exportPath.default;
|
|
534
|
-
if (typeof importPath === 'string') {
|
|
535
|
-
return getNodeModulesRelativePath(join(moduleDir, importPath), fromFile);
|
|
536
|
-
}
|
|
568
|
+
const resolved = resolveExportValue(exportPath);
|
|
569
|
+
if (resolved) {
|
|
570
|
+
return getNodeModulesRelativePath(join(moduleDir, resolved), fromFile);
|
|
537
571
|
}
|
|
538
572
|
}
|
|
539
573
|
}
|