CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-get-tsconfig

Find and parse the tsconfig.json file from a directory path

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

path-resolution.mddocs/

Module Path Resolution

Module path resolution functionality for resolving import specifiers using TypeScript's path mapping configuration from compilerOptions.paths and baseUrl.

Capabilities

Path Matcher Creation

Creates a path matcher function that resolves module specifiers according to TypeScript's path mapping rules.

/**
 * Creates a path matcher function based on tsconfig paths configuration
 * @param tsconfig - The parsed tsconfig result from getTsconfig or parseTsconfig
 * @returns Path matcher function or null if no paths/baseUrl configuration exists
 */
function createPathsMatcher(
  tsconfig: TsConfigResult
): ((specifier: string) => string[]) | null;

/**
 * Function that resolves a module specifier to possible file paths
 * @param specifier - The import specifier to resolve (e.g., "@/utils", "lodash")
 * @returns Array of possible absolute file paths to check, empty if no matches
 */
type PathsMatcher = (specifier: string) => string[];

Usage Examples:

import { getTsconfig, createPathsMatcher, type TsConfigResult } from "get-tsconfig";

const tsconfig = getTsconfig("./my-project");
const pathsMatcher = createPathsMatcher(tsconfig);

if (pathsMatcher) {
  // Resolve path-mapped imports
  const utilsPaths = pathsMatcher("@/utils");          // ["/project/src/utils"]
  const componentPaths = pathsMatcher("@/components/Button"); // ["/project/src/components/Button"]
  
  // Relative imports return empty array (handled by normal resolution)
  const relativePaths = pathsMatcher("./local-file"); // []
  
  // Non-matching specifiers fall back to baseUrl resolution
  const basePaths = pathsMatcher("some-module");       // ["/project/src/some-module"] if baseUrl is set
}

Path Mapping Configuration

Path resolution works with TypeScript's compilerOptions.paths and compilerOptions.baseUrl settings:

// Example tsconfig.json with path mapping
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@/*": ["./utils/*", "./lib/*"],
      "@components/*": ["./components/*"],
      "~/*": ["../shared/*"]
    }
  }
}

Resolution Algorithm

The path matcher implements TypeScript's module resolution logic:

  1. Exact Match: Check for exact pattern matches first
  2. Wildcard Patterns: Process patterns with * wildcards, preferring longer prefixes
  3. Substitution: Replace wildcards in matched patterns with the corresponding part of the specifier
  4. BaseUrl Fallback: If no patterns match and baseUrl is set, try baseUrl + specifier
  5. Empty Result: Return empty array for relative paths or when no configuration exists

Pattern Matching Rules:

  • Patterns can have at most one * wildcard
  • Substitutions can have at most one * wildcard
  • Longer prefix patterns take precedence over shorter ones
  • First exact match takes precedence over wildcard patterns

Wildcard Pattern Examples

// Given tsconfig paths configuration:
// "@lib/*": ["./libraries/*", "./vendor/*"]

const pathsMatcher = createPathsMatcher(tsconfig);

// Resolves "@lib/utils" to:
const paths = pathsMatcher("@lib/utils");
// Returns: ["/project/src/libraries/utils", "/project/src/vendor/utils"]

// The "*" in the pattern matches "utils"
// The "*" in substitutions is replaced with "utils"

BaseUrl Resolution

When no path patterns match, baseUrl provides fallback resolution:

// Given tsconfig with baseUrl: "./src" and no matching paths
const pathsMatcher = createPathsMatcher(tsconfig);

// Non-relative specifier with baseUrl fallback
const paths = pathsMatcher("helpers/format");
// Returns: ["/project/src/helpers/format"]

Integration with Module Resolvers

Common integration pattern with custom module resolution systems:

import { getTsconfig, createPathsMatcher, type TsConfigResult } from "get-tsconfig";
import { existsSync } from "fs";
import { resolve } from "path";

function resolveModule(specifier: string, fromFile: string): string | null {
  const tsconfig = getTsconfig(fromFile);
  const pathsMatcher = createPathsMatcher(tsconfig);
  
  if (pathsMatcher) {
    const candidatePaths = pathsMatcher(specifier);
    
    // Try each candidate path with common extensions
    for (const candidatePath of candidatePaths) {
      const extensions = ['.ts', '.tsx', '.js', '.jsx', '.d.ts'];
      
      for (const ext of extensions) {
        const fullPath = candidatePath + ext;
        if (existsSync(fullPath)) {
          return fullPath;
        }
      }
      
      // Try index files
      const indexPath = resolve(candidatePath, 'index.ts');
      if (existsSync(indexPath)) {
        return indexPath;
      }
    }
  }
  
  // Fallback to standard Node.js resolution
  return null;
}

Implicit BaseUrl Support

get-tsconfig handles TypeScript's implicit baseUrl behavior when paths are specified without baseUrl:

// tsconfig.json with paths but no explicit baseUrl
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

The library automatically uses the tsconfig directory as an implicit baseUrl for path resolution.

Error Handling

The path matcher handles various edge cases gracefully:

  • No Configuration: Returns null if no paths or baseUrl are configured
  • Invalid Patterns: Throws errors for patterns with multiple wildcards
  • Relative Specifiers: Returns empty array for relative imports (./file, ../file)
  • Empty Substitutions: Handles missing or empty substitution arrays
import { createPathsMatcher } from "get-tsconfig";

const pathsMatcher = createPathsMatcher(tsconfig);

if (pathsMatcher === null) {
  console.log("No path mapping configuration found");
} else {
  // Safe to use path matcher
  const paths = pathsMatcher("@/utils");
}

Build Tool Integration

Example integration with bundlers and build tools:

import { getTsconfig, createPathsMatcher, type TsConfigResult } from "get-tsconfig";

function createResolver(projectRoot: string) {
  const tsconfig = getTsconfig(projectRoot);
  const pathsMatcher = createPathsMatcher(tsconfig);
  
  return {
    resolve(specifier: string, importer: string): string[] {
      if (pathsMatcher) {
        const mappedPaths = pathsMatcher(specifier);
        if (mappedPaths.length > 0) {
          return mappedPaths;
        }
      }
      
      // Fallback to standard resolution
      return [specifier];
    }
  };
}

docs

file-matching.md

index.md

path-resolution.md

tile.json