Lerna project configuration management for monorepos with package discovery and workspace handling
npx @tessl/cli install tessl/npm-lerna--project@6.4.0Lerna project configuration management for monorepos, providing package discovery, workspace handling, and configuration resolution for Lerna-managed multi-package repositories.
npm install @lerna/projectconst { Project } = require("@lerna/project");
const { getPackages, getPackagesSync } = require("@lerna/project");For ES modules:
import { Project, getPackages, getPackagesSync } from "@lerna/project";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");The @lerna/project package is built around several key components:
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{,.*}"
}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[];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");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");
}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 } }
// }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 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");/**
* 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;
}The package throws ValidationError instances for configuration-related issues:
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);
}
}