ucn 3.8.26 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core/imports.js CHANGED
@@ -120,6 +120,10 @@ function resolveImport(importPath, fromFile, config = {}) {
120
120
  if (result) return result;
121
121
  }
122
122
  }
123
+
124
+ // Package self-reference (import own package by name)
125
+ const selfResolved = resolveSelfReference(importPath, fromDir, config);
126
+ if (selfResolved) return selfResolved;
123
127
  }
124
128
 
125
129
  // Check Go module imports
@@ -412,12 +416,124 @@ function resolveRustImport(importPath, fromFile, projectRoot) {
412
416
  /**
413
417
  * Try to resolve a path with various extensions
414
418
  */
419
+ // package.json lookup cache for self-reference resolution (dir -> info|null).
420
+ // Process-lifetime cache: package.json name/exports churn is rare enough that
421
+ // long-lived servers (MCP) tolerate it.
422
+ const _pkgCache = new Map();
423
+
424
+ function _findPackageJson(fromDir, stopDir) {
425
+ let current = fromDir;
426
+ for (let i = 0; i < 8; i++) {
427
+ let info;
428
+ if (_pkgCache.has(current)) {
429
+ info = _pkgCache.get(current);
430
+ } else {
431
+ info = null;
432
+ const candidate = path.join(current, 'package.json');
433
+ try {
434
+ if (fs.existsSync(candidate)) {
435
+ const pkg = JSON.parse(fs.readFileSync(candidate, 'utf-8'));
436
+ info = { dir: current, name: pkg.name, exports: pkg.exports, main: pkg.main };
437
+ }
438
+ } catch { /* unreadable or invalid JSON */ }
439
+ _pkgCache.set(current, info);
440
+ }
441
+ if (info) return info;
442
+ if (stopDir && current === stopDir) break;
443
+ const parent = path.dirname(current);
444
+ if (parent === current) break;
445
+ current = parent;
446
+ }
447
+ return null;
448
+ }
449
+
450
+ /** Flatten an exports-map entry to candidate targets (condition objects in
451
+ * insertion order, arrays in order). 'types' conditions are skipped — they
452
+ * name declaration files, not runtime sources. */
453
+ function _collectExportTargets(entry, out = []) {
454
+ if (typeof entry === 'string') {
455
+ out.push(entry);
456
+ } else if (Array.isArray(entry)) {
457
+ for (const e of entry) _collectExportTargets(e, out);
458
+ } else if (entry && typeof entry === 'object') {
459
+ for (const [cond, v] of Object.entries(entry)) {
460
+ if (cond === 'types') continue;
461
+ _collectExportTargets(v, out);
462
+ }
463
+ }
464
+ return out;
465
+ }
466
+
467
+ /**
468
+ * Package self-reference: a file importing its own package by name
469
+ * (`import * as z from "zod/v3"` inside the zod repo) — standard in monorepo
470
+ * tests and benchmarks. Resolves through package.json "exports" (conditional
471
+ * objects, arrays, '*' wildcards), accepting the first condition target that
472
+ * lands on a real file.
473
+ */
474
+ function resolveSelfReference(importPath, fromDir, config) {
475
+ const pkg = _findPackageJson(fromDir, config.root ? path.dirname(config.root) : null);
476
+ if (!pkg || !pkg.name) return null;
477
+ if (importPath !== pkg.name && !importPath.startsWith(pkg.name + '/')) return null;
478
+ const subpath = importPath === pkg.name ? '.' : './' + importPath.slice(pkg.name.length + 1);
479
+ const extensions = config.extensions || getExtensions(config.language);
480
+ const tryTargets = (entry, wildcard) => {
481
+ for (const target of _collectExportTargets(entry)) {
482
+ const concrete = wildcard != null ? target.replace(/\*/g, wildcard) : target;
483
+ const resolved = resolveFilePath(path.resolve(pkg.dir, concrete), extensions);
484
+ if (resolved) return resolved;
485
+ }
486
+ return null;
487
+ };
488
+ const exp = pkg.exports;
489
+ if (typeof exp === 'string') {
490
+ return subpath === '.' ? tryTargets(exp, null) : null;
491
+ }
492
+ if (exp && typeof exp === 'object') {
493
+ if (exp[subpath] !== undefined) {
494
+ const hit = tryTargets(exp[subpath], null);
495
+ if (hit) return hit;
496
+ }
497
+ for (const [key, val] of Object.entries(exp)) {
498
+ const star = key.indexOf('*');
499
+ if (star === -1) continue;
500
+ const pre = key.slice(0, star);
501
+ const post = key.slice(star + 1);
502
+ if (subpath.length > pre.length + post.length &&
503
+ subpath.startsWith(pre) && subpath.endsWith(post)) {
504
+ const wild = subpath.slice(pre.length, subpath.length - post.length);
505
+ const hit = tryTargets(val, wild);
506
+ if (hit) return hit;
507
+ }
508
+ }
509
+ return null;
510
+ }
511
+ // No exports map: bare name -> main/index; subpath -> direct file
512
+ if (subpath === '.') {
513
+ return (pkg.main && resolveFilePath(path.resolve(pkg.dir, pkg.main), extensions)) ||
514
+ resolveFilePath(path.resolve(pkg.dir, 'index'), extensions);
515
+ }
516
+ return resolveFilePath(path.resolve(pkg.dir, subpath), extensions);
517
+ }
518
+
415
519
  function resolveFilePath(basePath, extensions) {
416
520
  // Check exact path
417
521
  if (fs.existsSync(basePath) && fs.statSync(basePath).isFile()) {
418
522
  return basePath;
419
523
  }
420
524
 
525
+ // TS-ESM: explicit '.js'/'.mjs' specifiers refer to '.ts'/'.mts' sources
526
+ // (import specifiers name the compiled output). Remap before probing.
527
+ const esmRemap = { '.js': ['.ts', '.tsx'], '.jsx': ['.tsx'], '.mjs': ['.mts'], '.cjs': ['.cts'] };
528
+ const explicitExt = path.extname(basePath);
529
+ if (esmRemap[explicitExt]) {
530
+ const stem = basePath.slice(0, -explicitExt.length);
531
+ for (const tsExt of esmRemap[explicitExt]) {
532
+ const candidate = stem + tsExt;
533
+ try { if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate; } catch { /* skip */ }
534
+ }
535
+ }
536
+
421
537
  // Try adding extensions
422
538
  for (const ext of extensions) {
423
539
  const withExt = basePath + ext;
@@ -633,5 +749,6 @@ module.exports = {
633
749
  extractImports,
634
750
  extractExports,
635
751
  resolveImport,
636
- resolveFilePath
752
+ resolveFilePath,
753
+ findGoModule
637
754
  };