deslop-js 0.0.20-dev.9342b67 → 0.0.21-dev.3d2e8a1

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/dist/index.d.mts CHANGED
@@ -47,6 +47,7 @@ interface UnusedExport {
47
47
  interface UnusedDependency {
48
48
  name: string;
49
49
  isDevDependency: boolean;
50
+ reason: string;
50
51
  }
51
52
  interface CircularDependency {
52
53
  files: string[];
@@ -416,6 +417,7 @@ interface DeslopConfig {
416
417
  ignorePatterns: string[];
417
418
  includeExtensions: string[];
418
419
  tsConfigPath: string | undefined;
420
+ paths: Record<string, string[]> | undefined;
419
421
  reportTypes: boolean;
420
422
  includeEntryExports: boolean;
421
423
  reportRedundancy: boolean;
package/dist/index.mjs CHANGED
@@ -4851,7 +4851,7 @@ const extractNextConfigPluginFiles = (directory) => {
4851
4851
  const VITEST_INCLUDE_ITEM_PATTERN = /['"]([^'"]+)['"]/g;
4852
4852
  const COVERAGE_BLOCK_PATTERN = /coverage\s*:\s*\{/g;
4853
4853
  const TEST_MATCH_ARRAY_PATTERN = /testMatch\s*:\s*\[([^\]]*)\]/;
4854
- const STRING_LITERAL_PATTERN = /['"]([^'"]+)['"]/g;
4854
+ const STRING_LITERAL_PATTERN$1 = /['"]([^'"]+)['"]/g;
4855
4855
  const extractJestTestMatchPatterns = (directory) => {
4856
4856
  const configPaths = fg.sync(["jest.config.{ts,js,mjs,cjs}"], {
4857
4857
  cwd: directory,
@@ -4873,9 +4873,9 @@ const extractJestTestMatchPatterns = (directory) => {
4873
4873
  if (!testMatchMatch) continue;
4874
4874
  const arrayContent = testMatchMatch[1];
4875
4875
  const patterns = [];
4876
- STRING_LITERAL_PATTERN.lastIndex = 0;
4876
+ STRING_LITERAL_PATTERN$1.lastIndex = 0;
4877
4877
  let itemMatch;
4878
- while ((itemMatch = STRING_LITERAL_PATTERN.exec(arrayContent)) !== null) patterns.push(itemMatch[1]);
4878
+ while ((itemMatch = STRING_LITERAL_PATTERN$1.exec(arrayContent)) !== null) patterns.push(itemMatch[1]);
4879
4879
  if (patterns.length > 0) return convertJestTestMatchToGlobs(patterns);
4880
4880
  } catch {}
4881
4881
  return [];
@@ -6292,6 +6292,19 @@ const isPlatformBuiltinOrVirtualSpecifier = (specifier) => {
6292
6292
  return BUILTIN_SUBPATH_NODE_MODULES.has(baseName);
6293
6293
  };
6294
6294
 
6295
+ //#endregion
6296
+ //#region src/utils/sanitize-import-specifier.ts
6297
+ const sanitizeImportSpecifier = (specifier) => {
6298
+ if (specifier.startsWith("node:") || specifier.startsWith("data:") || specifier.includes("://")) return specifier;
6299
+ const lastLoaderSeparator = specifier.lastIndexOf("!");
6300
+ let cleaned = lastLoaderSeparator === -1 ? specifier : specifier.slice(lastLoaderSeparator + 1);
6301
+ const queryIndex = cleaned.indexOf("?");
6302
+ if (queryIndex !== -1) cleaned = cleaned.slice(0, queryIndex);
6303
+ const fragmentIndex = cleaned.indexOf("#", 1);
6304
+ if (fragmentIndex !== -1) cleaned = cleaned.slice(0, fragmentIndex);
6305
+ return cleaned || specifier;
6306
+ };
6307
+
6295
6308
  //#endregion
6296
6309
  //#region src/resolver/resolve.ts
6297
6310
  const fileExistsCache = /* @__PURE__ */ new Map();
@@ -6356,6 +6369,50 @@ const resolvePathWithExtensionFallback = (candidatePath) => {
6356
6369
  }
6357
6370
  return candidatePath;
6358
6371
  };
6372
+ const resolveAliasTarget = (target) => {
6373
+ if (existsAsFile(target)) return target;
6374
+ for (const extension of RESOLVER_EXTENSIONS) if (cachedExistsSync(target + extension)) return target + extension;
6375
+ const sourceTarget = target.replace(/\.[cm]?js$/, "");
6376
+ if (sourceTarget !== target) {
6377
+ for (const extension of RESOLVER_EXTENSIONS) if (cachedExistsSync(sourceTarget + extension)) return sourceTarget + extension;
6378
+ }
6379
+ const indexCandidate = join(target, "index");
6380
+ for (const extension of RESOLVER_EXTENSIONS) if (cachedExistsSync(indexCandidate + extension)) return indexCandidate + extension;
6381
+ };
6382
+ const pathMappingSpecificity = (mapping) => mapping.isWildcard ? mapping.prefix.length + mapping.suffix.length : Number.MAX_SAFE_INTEGER;
6383
+ const compilePathMappings = (entries) => {
6384
+ const compiled = [];
6385
+ for (const [pattern, targets] of entries) {
6386
+ const wildcardIndex = pattern.indexOf("*");
6387
+ if (wildcardIndex === -1) compiled.push({
6388
+ prefix: pattern,
6389
+ suffix: "",
6390
+ isWildcard: false,
6391
+ targets
6392
+ });
6393
+ else compiled.push({
6394
+ prefix: pattern.slice(0, wildcardIndex),
6395
+ suffix: pattern.slice(wildcardIndex + 1),
6396
+ isWildcard: true,
6397
+ targets
6398
+ });
6399
+ }
6400
+ compiled.sort((left, right) => pathMappingSpecificity(right) - pathMappingSpecificity(left));
6401
+ return compiled;
6402
+ };
6403
+ const matchCompiledMapping = (specifier, mappings) => {
6404
+ for (const mapping of mappings) {
6405
+ let matchedWildcard = "";
6406
+ if (mapping.isWildcard) {
6407
+ if (!specifier.startsWith(mapping.prefix) || !specifier.endsWith(mapping.suffix)) continue;
6408
+ matchedWildcard = specifier.slice(mapping.prefix.length, specifier.length - mapping.suffix.length);
6409
+ } else if (specifier !== mapping.prefix) continue;
6410
+ for (const target of mapping.targets) {
6411
+ const resolved = resolveAliasTarget(target.replace("*", matchedWildcard));
6412
+ if (resolved) return resolved;
6413
+ }
6414
+ }
6415
+ };
6359
6416
  const COMMON_RESOLVER_OPTIONS = {
6360
6417
  conditionNames: [
6361
6418
  "import",
@@ -6387,11 +6444,26 @@ const WEBPACK_CONFIG_GLOBS = [
6387
6444
  "**/webpack.config*.{js,ts,mjs,cjs}",
6388
6445
  "**/webpack*.config*.babel.{js,ts}"
6389
6446
  ];
6390
- const WEBPACK_ALIAS_BLOCK_PATTERN = /alias\s*:\s*\{([\s\S]*?)\}/g;
6391
- const WEBPACK_ALIAS_ENTRY_PATTERN = /["']?([@\w$./-]+)["']?\s*:\s*(?:path\.(?:resolve|join)\(\s*__dirname\s*,\s*((?:["'][^"']+["']\s*,?\s*)+)\)|["']([^"']+)["'])/g;
6447
+ const VITE_CONFIG_GLOBS = [
6448
+ "vite.config.{js,ts,mjs,cjs,mts,cts}",
6449
+ "vitest.config.{js,ts,mjs,cjs,mts,cts}",
6450
+ "**/vite.config.{js,ts,mjs,cjs,mts,cts}",
6451
+ "**/vitest.config.{js,ts,mjs,cjs,mts,cts}"
6452
+ ];
6453
+ const BABEL_CONFIG_GLOBS = [
6454
+ "babel.config.{js,cjs,mjs,json}",
6455
+ ".babelrc",
6456
+ ".babelrc.{js,cjs,mjs,json}",
6457
+ "**/babel.config.{js,cjs,mjs,json}"
6458
+ ];
6459
+ const JEST_CONFIG_GLOBS = ["jest.config.{js,ts,mjs,cjs,json}", "**/jest.config.{js,ts,mjs,cjs,json}"];
6460
+ const ALIAS_BLOCK_PATTERN = /alias\s*:\s*\{([\s\S]*?)\}/g;
6461
+ const ALIAS_ENTRY_PATTERN = /["']?([@\w$./-]+)["']?\s*:\s*(?:path\.(?:resolve|join)\(\s*__dirname\s*,\s*((?:["'][^"']+["']\s*,?\s*)+)\)|fileURLToPath\(\s*new URL\(\s*["']([^"']+)["']\s*,\s*import\.meta\.url\s*\)\s*\)|["']([^"']+)["'])/g;
6462
+ const JEST_MODULE_NAME_MAPPER_BLOCK_PATTERN = /moduleNameMapper\s*:\s*\{([\s\S]*?)\}/g;
6463
+ const JEST_MODULE_NAME_MAPPER_ENTRY_PATTERN = /["']([^"']+)["']\s*:\s*["']([^"']+)["']/g;
6392
6464
  const WEBPACK_MODULES_BLOCK_PATTERN = /modules\s*:\s*\[([\s\S]*?)\]/g;
6393
6465
  const WEBPACK_PATH_CALL_PATTERN = /path\.(?:resolve|join)\(\s*__dirname\s*,\s*((?:["'][^"']+["']\s*,?\s*)+)\)/g;
6394
- const WEBPACK_STRING_LITERAL_PATTERN = /["']([^"']+)["']/g;
6466
+ const STRING_LITERAL_PATTERN = /["']([^"']+)["']/g;
6395
6467
  const TSCONFIG_FILENAMES = [
6396
6468
  "tsconfig.json",
6397
6469
  "tsconfig.web.json",
@@ -6448,15 +6520,15 @@ const isInsideDirectory = (filePath, directory) => {
6448
6520
  const extractQuotedSegments = (value) => {
6449
6521
  const segments = [];
6450
6522
  let segmentMatch;
6451
- WEBPACK_STRING_LITERAL_PATTERN.lastIndex = 0;
6452
- while ((segmentMatch = WEBPACK_STRING_LITERAL_PATTERN.exec(value)) !== null) segments.push(segmentMatch[1]);
6523
+ STRING_LITERAL_PATTERN.lastIndex = 0;
6524
+ while ((segmentMatch = STRING_LITERAL_PATTERN.exec(value)) !== null) segments.push(segmentMatch[1]);
6453
6525
  return segments;
6454
6526
  };
6455
- const resolveWebpackPathValue = (value, configDirectory) => {
6527
+ const resolveConfigPathValue = (value, configDirectory) => {
6456
6528
  if (isAbsolute(value)) return value;
6457
6529
  return resolve(configDirectory, value);
6458
6530
  };
6459
- const findWebpackConfigScope = (configPath, rootDir) => {
6531
+ const findConfigScope = (configPath, rootDir) => {
6460
6532
  let currentDirectory = dirname(configPath);
6461
6533
  const absoluteRoot = resolve(rootDir);
6462
6534
  while (currentDirectory.length >= absoluteRoot.length) {
@@ -6467,24 +6539,25 @@ const findWebpackConfigScope = (configPath, rootDir) => {
6467
6539
  }
6468
6540
  return absoluteRoot;
6469
6541
  };
6470
- const extractWebpackAliases = (content, configDirectory) => {
6542
+ const extractBundlerAliases = (content, configDirectory) => {
6471
6543
  const aliases = [];
6472
6544
  let aliasBlockMatch;
6473
- WEBPACK_ALIAS_BLOCK_PATTERN.lastIndex = 0;
6474
- while ((aliasBlockMatch = WEBPACK_ALIAS_BLOCK_PATTERN.exec(content)) !== null) {
6545
+ ALIAS_BLOCK_PATTERN.lastIndex = 0;
6546
+ while ((aliasBlockMatch = ALIAS_BLOCK_PATTERN.exec(content)) !== null) {
6475
6547
  const aliasBlock = aliasBlockMatch[1];
6476
6548
  let aliasEntryMatch;
6477
- WEBPACK_ALIAS_ENTRY_PATTERN.lastIndex = 0;
6478
- while ((aliasEntryMatch = WEBPACK_ALIAS_ENTRY_PATTERN.exec(aliasBlock)) !== null) {
6549
+ ALIAS_ENTRY_PATTERN.lastIndex = 0;
6550
+ while ((aliasEntryMatch = ALIAS_ENTRY_PATTERN.exec(aliasBlock)) !== null) {
6479
6551
  const rawName = aliasEntryMatch[1];
6480
6552
  const pathCallSegments = aliasEntryMatch[2];
6481
- const stringTarget = aliasEntryMatch[3];
6482
- if (!pathCallSegments && !stringTarget) continue;
6553
+ const fileUrlTarget = aliasEntryMatch[3];
6554
+ const stringTarget = aliasEntryMatch[4];
6483
6555
  const isExact = rawName.endsWith("$");
6484
6556
  const name = isExact ? rawName.slice(0, -1) : rawName.replace(/\/$/, "");
6485
6557
  let targetDirectory;
6486
6558
  if (pathCallSegments) targetDirectory = resolve(configDirectory, ...extractQuotedSegments(pathCallSegments));
6487
- else if (stringTarget) targetDirectory = resolveWebpackPathValue(stringTarget, configDirectory);
6559
+ else if (fileUrlTarget) targetDirectory = resolve(configDirectory, fileUrlTarget);
6560
+ else if (stringTarget) targetDirectory = resolveConfigPathValue(stringTarget, configDirectory);
6488
6561
  else continue;
6489
6562
  aliases.push({
6490
6563
  name,
@@ -6495,6 +6568,32 @@ const extractWebpackAliases = (content, configDirectory) => {
6495
6568
  }
6496
6569
  return aliases;
6497
6570
  };
6571
+ const compileJestModuleNameMapperAlias = (pattern, target, configDirectory) => {
6572
+ if (!target.includes("<rootDir>")) return void 0;
6573
+ const isWildcard = pattern.includes("(.*)") || pattern.includes("(.+)");
6574
+ const aliasName = pattern.replace(/^\^/, "").replace(/\$$/, "").replace(/\\(.)/g, "$1").replace(/\/?\((?:\.\*|\.\+)\)$/, "").replace(/\/$/, "");
6575
+ if (!aliasName) return void 0;
6576
+ return {
6577
+ name: aliasName,
6578
+ targetDirectory: resolve(target.replace(/<rootDir>/g, configDirectory).replace(/\/?\$\d+$/, "")),
6579
+ isExact: !isWildcard
6580
+ };
6581
+ };
6582
+ const extractJestModuleNameMapperAliases = (content, configDirectory) => {
6583
+ const aliases = [];
6584
+ let blockMatch;
6585
+ JEST_MODULE_NAME_MAPPER_BLOCK_PATTERN.lastIndex = 0;
6586
+ while ((blockMatch = JEST_MODULE_NAME_MAPPER_BLOCK_PATTERN.exec(content)) !== null) {
6587
+ const block = blockMatch[1];
6588
+ let entryMatch;
6589
+ JEST_MODULE_NAME_MAPPER_ENTRY_PATTERN.lastIndex = 0;
6590
+ while ((entryMatch = JEST_MODULE_NAME_MAPPER_ENTRY_PATTERN.exec(block)) !== null) {
6591
+ const alias = compileJestModuleNameMapperAlias(entryMatch[1], entryMatch[2], configDirectory);
6592
+ if (alias) aliases.push(alias);
6593
+ }
6594
+ }
6595
+ return aliases;
6596
+ };
6498
6597
  const extractWebpackModuleDirectories = (content, configDirectory) => {
6499
6598
  const moduleDirectories = [];
6500
6599
  let modulesBlockMatch;
@@ -6505,17 +6604,39 @@ const extractWebpackModuleDirectories = (content, configDirectory) => {
6505
6604
  WEBPACK_PATH_CALL_PATTERN.lastIndex = 0;
6506
6605
  while ((pathCallMatch = WEBPACK_PATH_CALL_PATTERN.exec(modulesBlock)) !== null) moduleDirectories.push(resolve(configDirectory, ...extractQuotedSegments(pathCallMatch[1])));
6507
6606
  let stringMatch;
6508
- WEBPACK_STRING_LITERAL_PATTERN.lastIndex = 0;
6509
- while ((stringMatch = WEBPACK_STRING_LITERAL_PATTERN.exec(modulesBlock)) !== null) {
6607
+ STRING_LITERAL_PATTERN.lastIndex = 0;
6608
+ while ((stringMatch = STRING_LITERAL_PATTERN.exec(modulesBlock)) !== null) {
6510
6609
  const moduleDirectory = stringMatch[1];
6511
6610
  if (moduleDirectory === "node_modules") continue;
6512
- moduleDirectories.push(resolveWebpackPathValue(moduleDirectory, configDirectory));
6611
+ moduleDirectories.push(resolveConfigPathValue(moduleDirectory, configDirectory));
6513
6612
  }
6514
6613
  }
6515
6614
  return [...new Set(moduleDirectories)];
6516
6615
  };
6517
- const loadWebpackResolverConfigs = (rootDir) => {
6518
- const configPaths = fg.sync(WEBPACK_CONFIG_GLOBS, {
6616
+ const isJestConfigPath = (configPath) => /(?:^|[\\/])jest\.config\.[^\\/]+$/.test(configPath);
6617
+ const isWebpackConfigPath = (configPath) => /webpack/.test(configPath);
6618
+ const extractPackageJsonJestAliases = (rootDir) => {
6619
+ try {
6620
+ const moduleNameMapper = JSON.parse(cachedReadFileSync(join(rootDir, "package.json")))?.jest?.moduleNameMapper;
6621
+ if (!moduleNameMapper || typeof moduleNameMapper !== "object") return [];
6622
+ const aliases = [];
6623
+ for (const [pattern, target] of Object.entries(moduleNameMapper)) {
6624
+ if (typeof target !== "string") continue;
6625
+ const alias = compileJestModuleNameMapperAlias(pattern, target, rootDir);
6626
+ if (alias) aliases.push(alias);
6627
+ }
6628
+ return aliases;
6629
+ } catch {
6630
+ return [];
6631
+ }
6632
+ };
6633
+ const loadBundlerAliasConfigs = (rootDir) => {
6634
+ const configPaths = fg.sync([
6635
+ ...WEBPACK_CONFIG_GLOBS,
6636
+ ...VITE_CONFIG_GLOBS,
6637
+ ...BABEL_CONFIG_GLOBS,
6638
+ ...JEST_CONFIG_GLOBS
6639
+ ], {
6519
6640
  cwd: rootDir,
6520
6641
  absolute: true,
6521
6642
  onlyFiles: true,
@@ -6530,17 +6651,24 @@ const loadWebpackResolverConfigs = (rootDir) => {
6530
6651
  for (const configPath of configPaths) try {
6531
6652
  const content = cachedReadFileSync(configPath);
6532
6653
  const configDirectory = dirname(configPath);
6533
- const aliases = extractWebpackAliases(content, configDirectory);
6534
- const moduleDirectories = extractWebpackModuleDirectories(content, configDirectory);
6654
+ const aliases = extractBundlerAliases(content, configDirectory);
6655
+ if (isJestConfigPath(configPath)) aliases.push(...extractJestModuleNameMapperAliases(content, configDirectory));
6656
+ const moduleDirectories = isWebpackConfigPath(configPath) ? extractWebpackModuleDirectories(content, configDirectory) : [];
6535
6657
  if (aliases.length === 0 && moduleDirectories.length === 0) continue;
6536
6658
  configs.push({
6537
- scopeDirectory: findWebpackConfigScope(configPath, rootDir),
6659
+ scopeDirectory: findConfigScope(configPath, rootDir),
6538
6660
  aliases,
6539
6661
  moduleDirectories
6540
6662
  });
6541
6663
  } catch {
6542
6664
  continue;
6543
6665
  }
6666
+ const packageJsonJestAliases = extractPackageJsonJestAliases(rootDir);
6667
+ if (packageJsonJestAliases.length > 0) configs.push({
6668
+ scopeDirectory: resolve(rootDir),
6669
+ aliases: packageJsonJestAliases,
6670
+ moduleDirectories: []
6671
+ });
6544
6672
  return configs;
6545
6673
  };
6546
6674
  const createResolver = (config, workspacePackages = [], options = {}) => {
@@ -6579,7 +6707,36 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
6579
6707
  };
6580
6708
  const workspaceNameToDirectory = /* @__PURE__ */ new Map();
6581
6709
  for (const workspacePackage of workspacePackages) workspaceNameToDirectory.set(workspacePackage.name, workspacePackage.directory);
6582
- const webpackResolverConfigs = (options.monorepoRoot && options.monorepoRoot !== config.rootDir ? [config.rootDir, options.monorepoRoot] : [config.rootDir]).flatMap(loadWebpackResolverConfigs).sort((leftConfig, rightConfig) => rightConfig.scopeDirectory.length - leftConfig.scopeDirectory.length);
6710
+ const structuralAliasToDirectory = /* @__PURE__ */ new Map();
6711
+ const workspaceScopes = /* @__PURE__ */ new Set();
6712
+ for (const workspacePackage of workspacePackages) {
6713
+ if (!workspacePackage.name.startsWith("@")) continue;
6714
+ const slashIndex = workspacePackage.name.indexOf("/");
6715
+ if (slashIndex !== -1) workspaceScopes.add(workspacePackage.name.slice(0, slashIndex));
6716
+ }
6717
+ if (workspaceScopes.size > 0) {
6718
+ const ambiguousStructuralKeys = /* @__PURE__ */ new Set();
6719
+ const registerStructuralAlias = (aliasKey, directory) => {
6720
+ if (workspaceNameToDirectory.has(aliasKey)) return;
6721
+ const existing = structuralAliasToDirectory.get(aliasKey);
6722
+ if (existing !== void 0 && existing !== directory) {
6723
+ ambiguousStructuralKeys.add(aliasKey);
6724
+ return;
6725
+ }
6726
+ structuralAliasToDirectory.set(aliasKey, directory);
6727
+ };
6728
+ for (const workspacePackage of workspacePackages) {
6729
+ const directoryBasename = basename(workspacePackage.directory);
6730
+ const slashIndex = workspacePackage.name.indexOf("/");
6731
+ const unscopedName = workspacePackage.name.startsWith("@") && slashIndex !== -1 ? workspacePackage.name.slice(slashIndex + 1) : workspacePackage.name;
6732
+ for (const scope of workspaceScopes) {
6733
+ registerStructuralAlias(`${scope}/${directoryBasename}`, workspacePackage.directory);
6734
+ if (unscopedName && unscopedName !== directoryBasename) registerStructuralAlias(`${scope}/${unscopedName}`, workspacePackage.directory);
6735
+ }
6736
+ }
6737
+ for (const ambiguousKey of ambiguousStructuralKeys) structuralAliasToDirectory.delete(ambiguousKey);
6738
+ }
6739
+ const bundlerAliasConfigs = (options.monorepoRoot && options.monorepoRoot !== config.rootDir ? [config.rootDir, options.monorepoRoot] : [config.rootDir]).flatMap(loadBundlerAliasConfigs).sort((leftConfig, rightConfig) => rightConfig.scopeDirectory.length - leftConfig.scopeDirectory.length);
6583
6740
  let rootTsconfigPath;
6584
6741
  if (config.tsConfigPath) rootTsconfigPath = resolve(config.rootDir, config.tsConfigPath);
6585
6742
  else {
@@ -6597,6 +6754,7 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
6597
6754
  }
6598
6755
  const tsconfigPathCache = /* @__PURE__ */ new Map();
6599
6756
  const tsconfigPathAliasCache = /* @__PURE__ */ new Map();
6757
+ const tsconfigCompiledAliasCache = /* @__PURE__ */ new Map();
6600
6758
  const findTsconfigForFile = (filePath) => {
6601
6759
  const fileDir = dirname(filePath);
6602
6760
  const cached = tsconfigPathCache.get(fileDir);
@@ -6743,64 +6901,127 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
6743
6901
  tsconfigPathAliasCache.set(tsconfigFile, aliasMap);
6744
6902
  return aliasMap;
6745
6903
  };
6904
+ const getCompiledPathAliases = (tsconfigFile) => {
6905
+ const cached = tsconfigCompiledAliasCache.get(tsconfigFile);
6906
+ if (cached) return cached;
6907
+ const compiled = compilePathMappings(getPathAliases(tsconfigFile));
6908
+ tsconfigCompiledAliasCache.set(tsconfigFile, compiled);
6909
+ return compiled;
6910
+ };
6746
6911
  const tryResolveViaPathAlias = (specifier, fromFile) => {
6747
6912
  const tsconfigFile = findTsconfigForFile(fromFile);
6748
6913
  if (!tsconfigFile) return void 0;
6749
- const aliases = getPathAliases(tsconfigFile);
6750
- for (const [pattern, targetPatterns] of aliases) {
6751
- const wildcardIndex = pattern.indexOf("*");
6752
- if (wildcardIndex === -1) {
6753
- if (specifier === pattern) for (const targetPattern of targetPatterns) {
6754
- const candidate = targetPattern.replace("*", "");
6755
- if (existsAsFile(candidate)) return candidate;
6756
- for (const ext of RESOLVER_EXTENSIONS) if (cachedExistsSync(candidate + ext)) return candidate + ext;
6757
- const indexCandidate = join(candidate, "index");
6758
- for (const ext of RESOLVER_EXTENSIONS) if (cachedExistsSync(indexCandidate + ext)) return indexCandidate + ext;
6759
- }
6760
- continue;
6761
- }
6762
- const prefix = pattern.slice(0, wildcardIndex);
6763
- const suffix = pattern.slice(wildcardIndex + 1);
6764
- if (!specifier.startsWith(prefix) || !specifier.endsWith(suffix)) continue;
6765
- const matchedWildcard = specifier.slice(prefix.length, specifier.length - suffix.length);
6766
- for (const targetPattern of targetPatterns) {
6767
- const resolvedTarget = targetPattern.replace("*", matchedWildcard);
6768
- if (existsAsFile(resolvedTarget)) return resolvedTarget;
6769
- for (const ext of RESOLVER_EXTENSIONS) if (cachedExistsSync(resolvedTarget + ext)) return resolvedTarget + ext;
6770
- const strippedTarget = resolvedTarget.replace(/\.[cm]?js$/, "");
6771
- if (strippedTarget !== resolvedTarget) {
6772
- for (const ext of RESOLVER_EXTENSIONS) if (cachedExistsSync(strippedTarget + ext)) return strippedTarget + ext;
6773
- }
6774
- const indexCandidate = join(resolvedTarget, "index");
6775
- for (const ext of RESOLVER_EXTENSIONS) if (cachedExistsSync(indexCandidate + ext)) return indexCandidate + ext;
6776
- }
6777
- }
6914
+ return matchCompiledMapping(specifier, getCompiledPathAliases(tsconfigFile));
6778
6915
  };
6779
6916
  const tryResolveFromDirectory = (directory, specifier) => {
6780
6917
  const candidatePath = resolvePathWithExtensionFallback(resolve(directory, specifier));
6781
6918
  if (existsAsFile(candidatePath)) return candidatePath;
6782
6919
  };
6783
- const tryResolveViaWebpackConfig = (specifier, fromFile) => {
6784
- if (webpackResolverConfigs.length === 0) return void 0;
6920
+ const tryResolveViaBundlerAlias = (specifier, fromFile) => {
6921
+ if (bundlerAliasConfigs.length === 0) return void 0;
6785
6922
  if (!isBareSpecifier(specifier)) return void 0;
6786
- for (const webpackConfig of webpackResolverConfigs) {
6787
- if (!isInsideDirectory(fromFile, webpackConfig.scopeDirectory)) continue;
6788
- for (const alias of webpackConfig.aliases) {
6923
+ for (const bundlerConfig of bundlerAliasConfigs) {
6924
+ if (!isInsideDirectory(fromFile, bundlerConfig.scopeDirectory)) continue;
6925
+ for (const alias of bundlerConfig.aliases) {
6789
6926
  if (alias.isExact && specifier !== alias.name) continue;
6790
6927
  const suffix = specifier === alias.name ? "" : specifier.startsWith(`${alias.name}/`) ? specifier.slice(alias.name.length + 1) : void 0;
6791
6928
  if (suffix === void 0) continue;
6792
6929
  const aliasCandidate = tryResolveFromDirectory(alias.targetDirectory, suffix);
6793
6930
  if (aliasCandidate) return aliasCandidate;
6794
6931
  }
6795
- for (const moduleDirectory of webpackConfig.moduleDirectories) {
6932
+ for (const moduleDirectory of bundlerConfig.moduleDirectories) {
6796
6933
  const moduleCandidate = tryResolveFromDirectory(moduleDirectory, specifier);
6797
6934
  if (moduleCandidate) return moduleCandidate;
6798
6935
  }
6799
6936
  }
6800
6937
  };
6938
+ const compiledConfigPaths = config.paths ? compilePathMappings(Object.entries(config.paths).map(([pattern, targets]) => [pattern, targets.map((target) => resolve(config.rootDir, target))])) : [];
6939
+ const tryResolveViaConfigPaths = (specifier) => compiledConfigPaths.length === 0 ? void 0 : matchCompiledMapping(specifier, compiledConfigPaths);
6940
+ const resolveWorkspaceSubpath = (workspaceDirectory, subpath) => {
6941
+ const workspacePackageJsonPath = join(workspaceDirectory, "package.json");
6942
+ try {
6943
+ const workspacePackageContent = cachedReadFileSync(workspacePackageJsonPath);
6944
+ const workspacePackageJson = JSON.parse(workspacePackageContent);
6945
+ let resolvedEntryPath;
6946
+ if (subpath && workspacePackageJson.exports) {
6947
+ const exportKey = `./${subpath}`;
6948
+ const exportValue = workspacePackageJson.exports[exportKey];
6949
+ if (typeof exportValue === "string") {
6950
+ const candidatePath = resolvePathWithExtensionFallback(resolve(workspaceDirectory, exportValue));
6951
+ resolvedEntryPath = existsAsFile(candidatePath) ? candidatePath : trySourceFallback(candidatePath);
6952
+ } else if (typeof exportValue === "object" && exportValue !== null) {
6953
+ const conditionValue = exportValue.import ?? exportValue.require ?? exportValue.default ?? exportValue.types;
6954
+ if (typeof conditionValue === "string") {
6955
+ const candidatePath = resolvePathWithExtensionFallback(resolve(workspaceDirectory, conditionValue));
6956
+ resolvedEntryPath = existsAsFile(candidatePath) ? candidatePath : trySourceFallback(candidatePath);
6957
+ }
6958
+ }
6959
+ if (!resolvedEntryPath) for (const [wildcardPattern, wildcardTarget] of Object.entries(workspacePackageJson.exports)) {
6960
+ if (typeof wildcardPattern !== "string" || !wildcardPattern.includes("*")) continue;
6961
+ const wildcardTargetRecord = typeof wildcardTarget === "object" && wildcardTarget !== null ? wildcardTarget : void 0;
6962
+ const wildcardTargetValue = typeof wildcardTarget === "string" ? wildcardTarget : wildcardTargetRecord ? String(wildcardTargetRecord["import"] ?? wildcardTargetRecord["require"] ?? wildcardTargetRecord["default"] ?? wildcardTargetRecord["types"] ?? "") : void 0;
6963
+ if (typeof wildcardTargetValue !== "string") continue;
6964
+ const wildcardPrefix = wildcardPattern.slice(0, wildcardPattern.indexOf("*"));
6965
+ const wildcardSuffix = wildcardPattern.slice(wildcardPattern.indexOf("*") + 1);
6966
+ if (exportKey.startsWith(wildcardPrefix) && exportKey.endsWith(wildcardSuffix)) {
6967
+ const matchedSegment = exportKey.slice(wildcardPrefix.length, exportKey.length - wildcardSuffix.length || void 0);
6968
+ const candidatePath = resolvePathWithExtensionFallback(resolve(workspaceDirectory, wildcardTargetValue.replace("*", matchedSegment)));
6969
+ resolvedEntryPath = existsAsFile(candidatePath) ? candidatePath : trySourceFallback(candidatePath);
6970
+ break;
6971
+ }
6972
+ }
6973
+ }
6974
+ if (subpath && !resolvedEntryPath) {
6975
+ const subpathCandidates = [resolve(workspaceDirectory, subpath), resolve(workspaceDirectory, "src", subpath)];
6976
+ for (const directSubpath of subpathCandidates) {
6977
+ for (const candidateExtension of RESOLVER_EXTENSIONS) {
6978
+ const candidate = directSubpath + candidateExtension;
6979
+ if (cachedExistsSync(candidate)) {
6980
+ resolvedEntryPath = candidate;
6981
+ break;
6982
+ }
6983
+ }
6984
+ if (resolvedEntryPath) break;
6985
+ for (const candidateExtension of RESOLVER_EXTENSIONS) {
6986
+ const indexCandidate = join(directSubpath, `index${candidateExtension}`);
6987
+ if (cachedExistsSync(indexCandidate)) {
6988
+ resolvedEntryPath = indexCandidate;
6989
+ break;
6990
+ }
6991
+ }
6992
+ if (resolvedEntryPath) break;
6993
+ }
6994
+ }
6995
+ if (!subpath) {
6996
+ const mainField = workspacePackageJson.main ?? workspacePackageJson.module;
6997
+ if (typeof mainField === "string") resolvedEntryPath = resolve(workspaceDirectory, mainField);
6998
+ if (!resolvedEntryPath && workspacePackageJson.exports?.["."]) {
6999
+ const dotExport = workspacePackageJson.exports["."];
7000
+ if (typeof dotExport === "string") resolvedEntryPath = resolve(workspaceDirectory, dotExport);
7001
+ else if (typeof dotExport === "object" && dotExport !== null) {
7002
+ const conditionValue = dotExport.import ?? dotExport.require ?? dotExport.default ?? dotExport.types;
7003
+ if (typeof conditionValue === "string") resolvedEntryPath = resolve(workspaceDirectory, conditionValue);
7004
+ }
7005
+ }
7006
+ }
7007
+ if (resolvedEntryPath) {
7008
+ const finalPath = resolveSourcePath(resolvedEntryPath, workspaceDirectory) ?? resolvedEntryPath;
7009
+ if (cachedExistsSync(finalPath)) return finalPath;
7010
+ const sourceFallbackPath = trySourceFallback(resolvedEntryPath);
7011
+ if (sourceFallbackPath) return sourceFallbackPath;
7012
+ }
7013
+ } catch {}
7014
+ };
7015
+ const tryResolveViaWorkspaceStructure = (specifier) => {
7016
+ if (structuralAliasToDirectory.size === 0) return void 0;
7017
+ if (!isBareSpecifier(specifier)) return void 0;
7018
+ const packageKey = extractPackageNameFromSpecifier(specifier);
7019
+ const directory = structuralAliasToDirectory.get(packageKey);
7020
+ if (!directory) return void 0;
7021
+ return resolveWorkspaceSubpath(directory, specifier.length > packageKey.length ? specifier.slice(packageKey.length + 1) : "");
7022
+ };
6801
7023
  const resolveModule = (specifier, fromFile) => {
6802
- const queryIndex = specifier.indexOf("?");
6803
- const cleanedSpecifier = queryIndex !== -1 ? specifier.slice(0, queryIndex) : specifier;
7024
+ const cleanedSpecifier = sanitizeImportSpecifier(specifier);
6804
7025
  const fromDir = dirname(fromFile);
6805
7026
  const cacheKey = `${fromDir}::${cleanedSpecifier}`;
6806
7027
  const cached = resolveResultCache.get(cacheKey);
@@ -6830,96 +7051,16 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
6830
7051
  const packageName = extractPackageNameFromSpecifier(cleanedSpecifier);
6831
7052
  const workspaceDirectory = workspaceNameToDirectory.get(packageName);
6832
7053
  if (workspaceDirectory) {
6833
- const subpath = cleanedSpecifier.slice(packageName.length + 1);
6834
- const workspacePackageJsonPath = join(workspaceDirectory, "package.json");
6835
- try {
6836
- const workspacePackageContent = cachedReadFileSync(workspacePackageJsonPath);
6837
- const workspacePackageJson = JSON.parse(workspacePackageContent);
6838
- let resolvedEntryPath;
6839
- if (subpath && workspacePackageJson.exports) {
6840
- const exportKey = `./${subpath}`;
6841
- const exportValue = workspacePackageJson.exports[exportKey];
6842
- if (typeof exportValue === "string") {
6843
- const candidatePath = resolvePathWithExtensionFallback(resolve(workspaceDirectory, exportValue));
6844
- resolvedEntryPath = existsAsFile(candidatePath) ? candidatePath : trySourceFallback(candidatePath);
6845
- } else if (typeof exportValue === "object" && exportValue !== null) {
6846
- const conditionValue = exportValue.import ?? exportValue.require ?? exportValue.default ?? exportValue.types;
6847
- if (typeof conditionValue === "string") {
6848
- const candidatePath = resolvePathWithExtensionFallback(resolve(workspaceDirectory, conditionValue));
6849
- resolvedEntryPath = existsAsFile(candidatePath) ? candidatePath : trySourceFallback(candidatePath);
6850
- }
6851
- }
6852
- if (!resolvedEntryPath) for (const [wildcardPattern, wildcardTarget] of Object.entries(workspacePackageJson.exports)) {
6853
- if (typeof wildcardPattern !== "string" || !wildcardPattern.includes("*")) continue;
6854
- const wildcardTargetRecord = typeof wildcardTarget === "object" && wildcardTarget !== null ? wildcardTarget : void 0;
6855
- const wildcardTargetValue = typeof wildcardTarget === "string" ? wildcardTarget : wildcardTargetRecord ? String(wildcardTargetRecord["import"] ?? wildcardTargetRecord["require"] ?? wildcardTargetRecord["default"] ?? wildcardTargetRecord["types"] ?? "") : void 0;
6856
- if (typeof wildcardTargetValue !== "string") continue;
6857
- const wildcardPrefix = wildcardPattern.slice(0, wildcardPattern.indexOf("*"));
6858
- const wildcardSuffix = wildcardPattern.slice(wildcardPattern.indexOf("*") + 1);
6859
- if (exportKey.startsWith(wildcardPrefix) && exportKey.endsWith(wildcardSuffix)) {
6860
- const matchedSegment = exportKey.slice(wildcardPrefix.length, exportKey.length - wildcardSuffix.length || void 0);
6861
- const candidatePath = resolvePathWithExtensionFallback(resolve(workspaceDirectory, wildcardTargetValue.replace("*", matchedSegment)));
6862
- resolvedEntryPath = existsAsFile(candidatePath) ? candidatePath : trySourceFallback(candidatePath);
6863
- break;
6864
- }
6865
- }
6866
- }
6867
- if (subpath && !resolvedEntryPath) {
6868
- const subpathCandidates = [resolve(workspaceDirectory, subpath), resolve(workspaceDirectory, "src", subpath)];
6869
- for (const directSubpath of subpathCandidates) {
6870
- for (const candidateExtension of RESOLVER_EXTENSIONS) {
6871
- const candidate = directSubpath + candidateExtension;
6872
- if (cachedExistsSync(candidate)) {
6873
- resolvedEntryPath = candidate;
6874
- break;
6875
- }
6876
- }
6877
- if (resolvedEntryPath) break;
6878
- for (const candidateExtension of RESOLVER_EXTENSIONS) {
6879
- const indexCandidate = join(directSubpath, `index${candidateExtension}`);
6880
- if (cachedExistsSync(indexCandidate)) {
6881
- resolvedEntryPath = indexCandidate;
6882
- break;
6883
- }
6884
- }
6885
- if (resolvedEntryPath) break;
6886
- }
6887
- }
6888
- if (!subpath) {
6889
- const mainField = workspacePackageJson.main ?? workspacePackageJson.module;
6890
- if (typeof mainField === "string") resolvedEntryPath = resolve(workspaceDirectory, mainField);
6891
- if (!resolvedEntryPath && workspacePackageJson.exports?.["."]) {
6892
- const dotExport = workspacePackageJson.exports["."];
6893
- if (typeof dotExport === "string") resolvedEntryPath = resolve(workspaceDirectory, dotExport);
6894
- else if (typeof dotExport === "object" && dotExport !== null) {
6895
- const conditionValue = dotExport.import ?? dotExport.require ?? dotExport.default ?? dotExport.types;
6896
- if (typeof conditionValue === "string") resolvedEntryPath = resolve(workspaceDirectory, conditionValue);
6897
- }
6898
- }
6899
- }
6900
- if (resolvedEntryPath) {
6901
- const finalPath = resolveSourcePath(resolvedEntryPath, workspaceDirectory) ?? resolvedEntryPath;
6902
- if (cachedExistsSync(finalPath)) {
6903
- const resolvedResult = {
6904
- resolvedPath: finalPath,
6905
- isExternal: false,
6906
- packageName: void 0
6907
- };
6908
- resolveResultCache.set(cacheKey, resolvedResult);
6909
- return resolvedResult;
6910
- }
6911
- const sourceFallbackPath = trySourceFallback(resolvedEntryPath);
6912
- if (sourceFallbackPath) {
6913
- const resolvedResult = {
6914
- resolvedPath: sourceFallbackPath,
6915
- isExternal: false,
6916
- packageName: void 0
6917
- };
6918
- resolveResultCache.set(cacheKey, resolvedResult);
6919
- return resolvedResult;
6920
- }
6921
- }
6922
- } catch {}
7054
+ const resolvedWorkspacePath = resolveWorkspaceSubpath(workspaceDirectory, cleanedSpecifier.slice(packageName.length + 1));
7055
+ if (resolvedWorkspacePath) {
7056
+ const resolvedResult = {
7057
+ resolvedPath: resolvedWorkspacePath,
7058
+ isExternal: false,
7059
+ packageName: void 0
7060
+ };
7061
+ resolveResultCache.set(cacheKey, resolvedResult);
7062
+ return resolvedResult;
7063
+ }
6923
7064
  }
6924
7065
  }
6925
7066
  const tsconfigForFile = findTsconfigForFile(fromFile);
@@ -6962,10 +7103,30 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
6962
7103
  resolveResultCache.set(cacheKey, resolvedResult);
6963
7104
  return resolvedResult;
6964
7105
  }
6965
- const webpackResolved = tryResolveViaWebpackConfig(cleanedSpecifier, fromFile);
6966
- if (webpackResolved) {
7106
+ const configPathResolved = tryResolveViaConfigPaths(cleanedSpecifier);
7107
+ if (configPathResolved) {
7108
+ const resolvedResult = {
7109
+ resolvedPath: configPathResolved,
7110
+ isExternal: false,
7111
+ packageName: void 0
7112
+ };
7113
+ resolveResultCache.set(cacheKey, resolvedResult);
7114
+ return resolvedResult;
7115
+ }
7116
+ const bundlerAliasResolved = tryResolveViaBundlerAlias(cleanedSpecifier, fromFile);
7117
+ if (bundlerAliasResolved) {
7118
+ const resolvedResult = {
7119
+ resolvedPath: bundlerAliasResolved,
7120
+ isExternal: false,
7121
+ packageName: void 0
7122
+ };
7123
+ resolveResultCache.set(cacheKey, resolvedResult);
7124
+ return resolvedResult;
7125
+ }
7126
+ const structuralResolved = tryResolveViaWorkspaceStructure(cleanedSpecifier);
7127
+ if (structuralResolved) {
6967
7128
  const resolvedResult = {
6968
- resolvedPath: webpackResolved,
7129
+ resolvedPath: structuralResolved,
6969
7130
  isExternal: false,
6970
7131
  packageName: void 0
6971
7132
  };
@@ -7909,9 +8070,11 @@ const detectStalePackages = (graph, config) => {
7909
8070
  const unusedDependencies = [];
7910
8071
  for (const dependencyName of candidateUnused) {
7911
8072
  const isDevDependency = declaredDependencies.get(dependencyName) ?? false;
8073
+ const dependencySection = isDevDependency ? "devDependencies" : "dependencies";
7912
8074
  unusedDependencies.push({
7913
8075
  name: dependencyName,
7914
- isDevDependency
8076
+ isDevDependency,
8077
+ reason: `"${dependencyName}" is declared in ${dependencySection} but is never imported or referenced by any source file, script, or config — remove it from package.json if it is genuinely unused`
7915
8078
  });
7916
8079
  }
7917
8080
  return unusedDependencies;
@@ -12648,6 +12811,7 @@ const defineConfig = (options) => ({
12648
12811
  ignorePatterns: options.ignorePatterns ?? [],
12649
12812
  includeExtensions: options.includeExtensions ?? DEFAULT_EXTENSIONS,
12650
12813
  tsConfigPath: options.tsConfigPath,
12814
+ paths: options.paths,
12651
12815
  reportTypes: options.reportTypes ?? false,
12652
12816
  includeEntryExports: options.includeEntryExports ?? false,
12653
12817
  reportRedundancy: options.reportRedundancy ?? true,