Skip to content

Latest commit

 

History

History
81 lines (57 loc) · 4.34 KB

File metadata and controls

81 lines (57 loc) · 4.34 KB

Yarn Detection

Requirements

Yarn detection relies on the presence of lockfiles generated by the Yarn package manager. The detector searches for the following file:

  • yarn.lock

Additionally, the detector requires a peer package.json file in the same directory as the yarn.lock file to determine root-level dependencies.

Detection strategy

Yarn detection is performed by the YarnLockComponentDetector, which parses yarn.lock files found in the scan directory. The detection process follows these steps:

  1. File Discovery: Searches for yarn.lock files while skipping specific folders:

    • node_modules
    • pnpm-store
    • \package\ (folder named "package")
  2. Lockfile Parsing: Uses the YarnLockFileFactory to parse the yarn.lock file format, which includes:

    • Package names and resolved versions
    • Dependency relationships (regular and optional dependencies)
    • Version ranges that each entry satisfies
  3. Root Dependency Identification: Reads the peer package.json file to determine which packages are direct (root) dependencies. This includes:

    • dependencies
    • devDependencies
    • peerDependencies
    • optionalDependencies
  4. Workspace Support: Handles Yarn workspaces by:

    • Reading workspace patterns from the root package.json
    • Using glob patterns to locate workspace package.json files
    • Merging dependencies from all workspace packages
    • Tracking component file paths for workspace dependencies
  5. Dependency Graph Construction: Builds a complete dependency graph by:

    • Registering all root dependencies first
    • Traversing the dependency tree using a breadth-first approach
    • Creating parent-child relationships based on lockfile data
    • Handling circular dependencies by tracking processed components
    • Marking development dependencies based on the root package.json

Lookup Table Strategy

The detector builds a lookup table where each key represents a package request (e.g., npm@^2.3.4) and maps to the resolved package entry. This is necessary because:

  • A single resolved package can satisfy multiple version ranges
  • The yarn.lock file explicitly lists all satisfied version strings
  • Example: npm@2.3.4 satisfies requests for npm@2, npm@2.3.4, and npm@^2.3.4

Dependency Types

The detector correctly identifies:

  • Root dependencies: Direct dependencies from package.json
  • Development dependencies: Marked when defined in devDependencies in the root package.json
  • Optional dependencies: Included in the dependency graph alongside regular dependencies
  • Workspace dependencies: Dependencies from workspace packages with their source file paths

Known limitations

  1. Requires peer package.json: If no package.json file is found in the same directory as the yarn.lock file, the components will not be registered as root dependencies. A warning will be logged and detection will be incomplete.

  2. Lockfile-only packages: If a package appears in yarn.lock but not in any package.json file (root or workspace), it will be registered as a component without parent relationships. This can happen with:

    • Orphaned dependencies from previous installations
    • Hoisted dependencies in workspaces
  3. Missing lockfile entries: If a package is declared in package.json but not found in the yarn.lock file, a parse failure is registered. This typically indicates:

    • The lockfile is out of sync with package.json
    • The project hasn't run yarn install after adding dependencies
  4. Duplicate entries: If the lockfile contains duplicate entries for the same package request, only the first entry is used and a warning is logged.

  5. Workspace glob pattern complexity: The detector uses DotNet.Globbing to match workspace patterns. Complex glob patterns may behave differently than Yarn's native glob implementation, particularly regarding:

    • Case sensitivity (handled differently on Windows vs. Linux)
    • Nested wildcard patterns
    • Negative patterns
  6. Parallel processing: While the detector enables parallelism for performance, this requires careful handling of the component recorder's thread safety guarantees.

  7. Development dependency propagation: All transitive dependencies of a development dependency are also marked as development dependencies, which may not always reflect the actual usage in the project.