manypkg

repository·main·Indexed 21 days ago

https://github.com/thinkmill/manypkg

A monorepo linter for ensuring consistency and correctness in package.json files across Yarn, npm, pnpm, Bun, or Lerna workspaces. It provides a CLI for checking and fixing common issues like dependency version mismatches, incorrect repository fields, and unsorted dependencies. The project also includes libraries such as @manypkg/find-root for monorepo root detection and @manypkg/get-packages for programmatically discovering packages within a monorepo.

Tokens
10.1K
Snippets
45
Records
59
Agent score
76%

What's inside manypkg

  1. Use `INTERNAL_DEV_DEP_NOT_STAR` to manage internal dependencies

    main

    In version 0.8.0, a new check INTERNAL_DEV_DEP_NOT_STAR was introduced. This check ensures that devDependencies pointing to internal workspace packages use the * version range instead of a specific semver range.

    Why use this? Internal dependencies are always linked in a monorepo. Using * prevents unnecessary package patches that would otherwise occur if an internal dependency's version moved outside a specific semver range, as the link remains valid regardless of the version.

    // Before (with specific range)
    {
      "name": "sunshine",
      "devDependencies": {
        "sun": "^1.0.0"
      }
    }
    
    // After manypkg fix
    {
      "name": "sunshine",
      "devDependencies": {
        "sun": "*"
      }
    }
  2. Configure Manypkg in package.json

    main

    You can configure Manypkg by adding a manypkg key to your root package.json file. Supported options include:

    • defaultBranch: The correct name for your repository branch (used by the Incorrect repository field rule). Defaults to main.
    • ignoredRules: An array of rule keys to disable. Defaults to [] (all rules enabled).
    • workspaceProtocol: Determines if the workspace: protocol for internal packages is required or allowed. Defaults to allow.
    {
      "name": "monorepo-root",
      "private": true,
      "manypkg": {
        "defaultBranch": "main",
        "ignoredRules": ["EXTERNAL_MISMATCH"],
        "workspaceProtocol": "allow"
      }
    }
  3. Bun monorepo support in Manypkg

    main
    Manypkg provides a BunTool implementation to detect and manage monorepos using Bun. A directory is recognized as a Bun monorepo root if it contains a package.json with a workspaces field (either as an array of strings or an object with a packages array) and a Bun lockfile (bun.lockb or bun.lock).
  4. Target specific packages with manypkg run

    main

    When using the run command, if you have packages with overlapping names (e.g., packages/pkg-a and packages/pkg-a-1), you can target the exact package by providing its exact directory name or its exact package name. This prevents the command from matching substrings of other packages.

    # Target by exact directory name
    yarn manypkg run packages/pkg-a
    
    # Target by exact package name
    yarn manypkg run @project/package-a
  5. Find the monorepo root with findRoot and findRootSync

    main

    Use @manypkg/find-root to locate the root directory of a monorepo. It supports workspaces managed by Yarn, npm, Lerna, pnpm, Bun, or Rush.

    • findRoot(startDir): An asynchronous function that returns a Promise resolving to the root directory path.
    • findRootSync(startDir): A synchronous function that returns the root directory path directly.

    Both functions require a starting directory (e.g., process.cwd()) as an argument.

    import { findRoot, findRootSync } from "@manypkg/find-root";
    
    // Asynchronous usage
    let dir = await findRoot(process.cwd());
    
    // Synchronous usage
    let dir = findRootSync(process.cwd());
  6. Use @manypkg/get-packages to retrieve monorepo packages

    main

    Use @manypkg/get-packages to programmatically discover packages within a monorepo. It automatically detects the monorepo manager being used (Yarn, npm, Lerna, pnpm, Bun, or Rush) and supports single-package repositories as well. The library uses @manypkg/find-root to locate the project root starting from the provided directory.

    It provides two main functions:

    • getPackages(directory): An asynchronous function that returns a promise.
    • getPackagesSync(directory): A synchronous function for simpler execution flows.
    import { getPackages, getPackagesSync } from "@manypkg/get-packages";
    
    // Asynchronous usage
    const { tool, packages, rootPackage, rootDir } = await getPackages(
      process.cwd()
    );
    
    // Synchronous usage
    const { tool, packages, rootPackage, rootDir } = getPackagesSync(process.cwd());
  7. Configure workspaceProtocol in manypkg

    main

    You can enforce that all internal package dependencies use the workspace: protocol by setting the workspaceProtocol option in your manypkg configuration within the root package.json.

    Configuration Key:

    • workspaceProtocol: Set to `