CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-lerna--project

Lerna project configuration management for monorepos with package discovery and workspace handling

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

Lerna Project

Lerna project configuration management for monorepos, providing package discovery, workspace handling, and configuration resolution for Lerna-managed multi-package repositories.

Package Information

  • Package Name: @lerna/project
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install @lerna/project

Core Imports

const { Project } = require("@lerna/project");
const { getPackages, getPackagesSync } = require("@lerna/project");

For ES modules:

import { Project, getPackages, getPackagesSync } from "@lerna/project";

Basic Usage

const { Project } = require("@lerna/project");

// Create a project instance from current working directory
const project = new Project();

// Get packages asynchronously
const packages = await project.getPackages();
console.log(packages.length); // Number of packages found

// Access project configuration
console.log(project.config.version); // Project version
console.log(project.rootPath); // Project root directory

// Static methods for convenience
const packages2 = await Project.getPackages("/path/to/monorepo");
const packagesSync = Project.getPackagesSync("/path/to/monorepo");

Architecture

The @lerna/project package is built around several key components:

  • Project Class: Central class representing a Lerna project with configuration and package discovery
  • Configuration System: Resolves lerna.json and package.json configurations with inheritance support
  • Package Discovery: Locates packages using glob patterns, supporting npm/yarn/pnpm workspaces
  • File System Integration: Handles file operations, license detection, and configuration persistence
  • Utility Functions: Configuration merging, deprecation handling, and file finding capabilities

Capabilities

Project Class

Core class representing a Lerna project and its configuration, providing access to packages, configuration, and project metadata.

/**
 * A representation of the entire project managed by Lerna
 * @param {string} [cwd] - Working directory (defaults to process.cwd())
 */
class Project {
  constructor(cwd?: string);
  
  // Static convenience methods
  static getPackages(cwd?: string): Promise<Package[]>;
  static getPackagesSync(cwd?: string): Package[];
  
  // Instance properties
  config: ProjectConfig;
  configNotFound: boolean;
  rootConfigLocation: string;
  rootPath: string;
  version: string;
  packageConfigs: string[];
  packageParentDirs: string[];
  manifest: Package;
  pnpmWorkspaceConfig: PnpmWorkspaceConfig;
  licensePath: string;
  fileFinder: FileFinder;
  
  // Instance methods
  getPackages(): Promise<Package[]>;
  getPackagesSync(): Package[];
  getPackageLicensePaths(): Promise<string[]>;
  isIndependent(): boolean;
  serializeConfig(): Promise<string>;
  
  // Static constants
  static PACKAGE_GLOB: string; // "packages/*"
  static LICENSE_GLOB: string; // "LICEN{S,C}E{,.*}"
}

Standalone Functions

Convenience functions providing direct access to package discovery without instantiating the Project class.

/**
 * Get packages for a project directory
 * @param {string} [cwd] - Working directory (defaults to process.cwd())
 * @returns {Promise<Package[]>} Array of Package instances
 */
function getPackages(cwd?: string): Promise<Package[]>;

/**
 * Synchronously get packages for a project directory
 * @param {string} [cwd] - Working directory (defaults to process.cwd())
 * @returns {Package[]} Array of Package instances
 */
function getPackagesSync(cwd?: string): Package[];

Package Discovery

Methods for discovering and enumerating packages within the monorepo.

/**
 * Asynchronously discover packages in the project
 * @returns {Promise<Package[]>} Array of Package instances
 */
Project.prototype.getPackages(): Promise<Package[]>;

/**
 * Synchronously discover packages in the project
 * @returns {Package[]} Array of Package instances
 */
Project.prototype.getPackagesSync(): Package[];

Usage Examples:

const { Project } = require("@lerna/project");

// Async package discovery
const project = new Project();
const packages = await project.getPackages();
packages.forEach(pkg => {
  console.log(`${pkg.name}@${pkg.version} at ${pkg.location}`);
});

// Sync package discovery
const packagesSync = project.getPackagesSync();
console.log(`Found ${packagesSync.length} packages`);

// Static methods
const allPackages = await Project.getPackages("/path/to/monorepo");

Configuration Management

Access and manage project configuration from lerna.json and package.json.

/**
 * Project version getter/setter
 */
get version(): string;
set version(val: string): void;

/**
 * Write configuration back to file system
 * @returns {Promise<string>} Path to written config file
 */
serializeConfig(): Promise<string>;

/**
 * Check if project uses independent versioning
 * @returns {boolean} True if independent versioning is enabled
 */
isIndependent(): boolean;

Usage Examples:

const project = new Project();

// Access configuration
console.log(project.config.version); // Current version
console.log(project.config.packages); // Package patterns
console.log(project.config.useWorkspaces); // Workspace usage

// Modify and save configuration
project.version = "2.0.0";
await project.serializeConfig();

// Check versioning mode
if (project.isIndependent()) {
  console.log("Using independent versioning");
}

Configuration Inheritance

Support for extending configurations from other modules using the extends property.

/**
 * Configuration can extend from locally-resolvable modules
 * Supports inheritance chains with circular reference detection
 */
interface ProjectConfig {
  extends?: string; // Path to module to extend from
  // ... other properties
}

Usage Examples:

// lerna.json
{
  "extends": "@my/lerna-config",
  "version": "1.0.0"
}

// The @my/lerna-config module exports:
module.exports = {
  "npmClient": "yarn",
  "useWorkspaces": true,
  "command": {
    "publish": {
      "conventionalCommits": true
    }
  }
};

// Resulting merged configuration:
const project = new Project();
console.log(project.config);
// {
//   "version": "1.0.0",
//   "npmClient": "yarn", 
//   "useWorkspaces": true,
//   "command": { "publish": { "conventionalCommits": true } }
// }

Workspace Integration

Support for npm, yarn, and pnpm workspace configurations.

/**
 * Get package configuration patterns
 * Resolves from pnpm-workspace.yaml, package.json workspaces, or lerna.json
 */
get packageConfigs(): string[];

/**
 * Get PNPM workspace configuration
 */
get pnpmWorkspaceConfig(): PnpmWorkspaceConfig;

/**
 * Get package parent directories
 */
get packageParentDirs(): string[];

Usage Examples:

const project = new Project();

// Get package patterns
const patterns = project.packageConfigs;
console.log(patterns); // ["packages/*", "tools/*"]

// Check workspace configuration
if (project.config.useWorkspaces) {
  const workspaces = project.manifest.get("workspaces");
  console.log("Using workspaces:", workspaces);
}

// PNPM-specific configuration
if (project.config.npmClient === "pnpm") {
  const pnpmConfig = project.pnpmWorkspaceConfig;
  console.log("PNPM packages:", pnpmConfig.packages);
}

File System Operations

File finding, license detection, and project metadata access.

/**
 * Get project root package.json as Package instance
 */
get manifest(): Package;

/**
 * Get path to project license file
 */
get licensePath(): string;

/**
 * Get file finder function for locating files in packages
 */
get fileFinder(): FileFinder;

/**
 * Get paths to package license files
 * @returns {Promise<string[]>} Array of license file paths
 */
getPackageLicensePaths(): Promise<string[]>;

Usage Examples:

const project = new Project();

// Access root package.json
const rootPackage = project.manifest;
console.log(rootPackage.name); // Root package name
console.log(rootPackage.get("scripts")); // Root scripts

// Find license files
const licensePath = project.licensePath;
const packageLicenses = await project.getPackageLicensePaths();

// Use file finder to locate files across packages
const fileFinder = project.fileFinder;
const readmeFiles = await fileFinder("README.md");
const testFiles = await fileFinder("*.test.js");

Types

/**
 * Project configuration object
 */
interface ProjectConfig {
  version: string;
  packages?: string[];
  useNx?: boolean;
  useWorkspaces?: boolean;
  npmClient?: string;
  command?: {
    [commandName: string]: Record<string, any>;
  };
  extends?: string;
  [key: string]: any; // Allow additional configuration properties
}

/**
 * PNPM workspace configuration from pnpm-workspace.yaml
 */
interface PnpmWorkspaceConfig {
  packages: string[];
}

/**
 * File finder function for locating files in packages
 * @param fileName - File name or glob pattern to search for
 * @param fileMapper - Optional function to transform file paths or file path arrays  
 * @param customGlobOpts - Optional glob options to override defaults
 * @returns Promise resolving to array of file paths, or transformed results if fileMapper is provided
 */
type FileFinder = <T = string>(
  fileName: string, 
  fileMapper?: (filePaths: string[]) => T[] | Promise<T[]>, 
  customGlobOpts?: object
) => Promise<T[]>;

/**
 * Package class from @lerna/package
 */
class Package {
  name: string;
  version: string;
  location: string;
  private: boolean;
  get(key: string): any;
  set(key: string, value: any): this;
  toJSON(): object;
}

Error Handling

The package throws ValidationError instances for configuration-related issues:

  • EWORKSPACES: Missing or invalid workspace configuration (npm/yarn workspaces or pnpm-workspace.yaml)
  • JSONError: Invalid JSON syntax in configuration files (lerna.json or package.json)
  • EPKGCONFIG: Invalid package configuration (e.g., node_modules pattern with globstars)
  • ERESOLVED: Configuration extends path cannot be resolved
  • ECIRCULAR: Circular extends references in configuration inheritance
  • ENOENT: Missing pnpm-workspace.yaml when using pnpm client

Example error handling:

const { Project } = require("@lerna/project");
const { ValidationError } = require("@lerna/validation-error");

try {
  const project = new Project();
  const packages = await project.getPackages();
} catch (error) {
  if (error instanceof ValidationError) {
    console.error("Configuration error:", error.message);
  } else {
    console.error("Unexpected error:", error);
  }
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@lerna/project@6.4.x
Publish Source
CLI
Badge
tessl/npm-lerna--project badge