List local packages that have changed since the last tagged release
npx @tessl/cli install tessl/npm-lerna--changed@6.6.0@lerna/changed is a command-line utility and programmatic API that identifies and lists local packages within a Lerna monorepo that have been modified since the last tagged release. It enables developers to track changes across their workspace for targeted builds, testing, and publishing workflows.
npm install @lerna/changed or lerna changed command via main lerna packageCommonJS (primary export format):
const changedIndex = require("@lerna/changed");
const { ChangedCommand } = require("@lerna/changed");Command module import:
const command = require("@lerna/changed/command");Available exports:
// Main factory function (default export)
const factory = require("@lerna/changed");
// Named export for class
const { ChangedCommand } = require("@lerna/changed");
// Command configuration
const commandConfig = require("@lerna/changed/command");# List changed packages since last tagged release
lerna changed
# Using alias
lerna updated
# With options
lerna changed --conventional-graduate
lerna changed --force-publish package-1
lerna changed --json
lerna changed --longconst factory = require("@lerna/changed");
// Create command instance using factory
const command = factory(process.argv);
// Execute if initialization successful
if (command.initialize()) {
command.execute();
}const { ChangedCommand } = require("@lerna/changed");
// Direct class instantiation
const command = new ChangedCommand(argv);
if (command.initialize()) {
command.execute();
}Lists packages that have changed since the last tagged release, supporting various detection modes and output formats.
/**
* Factory function that creates a ChangedCommand instance
* @param argv - Command line arguments array
* @returns ChangedCommand instance
*/
declare function factory(argv: NodeJS.Process["argv"]): ChangedCommand;Main command class providing changed package detection functionality.
interface ChangedCommandOptions extends CommandConfigOptions {
/** Enable conventional commits mode for determining changes */
conventionalCommits: boolean;
/** Detect prereleased packages that would graduate to non-prerelease */
conventionalGraduate: boolean;
/** Always include targeted packages when detecting changes */
forcePublish: boolean;
}
declare class ChangedCommand extends Command<ChangedCommandOptions> {
/** Formatted list of changed packages */
result: ReturnType<typeof listableFormat>;
/** Configuration compatibility with version and publish commands */
get otherCommandConfigs(): string[];
/**
* Initialize command, collect updates, and format results
* @returns false if no packages changed (prevents execution), void otherwise
*/
initialize(): boolean | void;
/** Execute command and output results to console */
execute(): void;
}Yargs command module configuration for CLI integration.
interface CommandModule {
/** Command name */
command: "changed";
/** Command aliases */
aliases: ["updated"];
/** Command description */
describe: "List local packages that have changed since the last tagged release";
/** Options builder function */
builder(yargs: any): any;
/** Command handler function */
handler(argv: any): any;
}Options specific to the changed command (CLI format):
interface ChangedOptions {
/** Enable conventional commits mode (hidden option, used internally) */
"conventional-commits"?: boolean;
/** Detect currently prereleased packages that would change to a non-prerelease version */
"conventional-graduate"?: boolean | string | string[];
/** Always include targeted packages when detecting changed packages, skipping default logic */
"force-publish"?: boolean | string | string[];
/** Ignore changes in files matched by glob(s) when detecting changed packages */
"ignore-changes"?: string[];
/** Include tags from merged branches when detecting changed packages */
"include-merged-tags"?: boolean;
}Inherited output formatting options from @lerna/core:
interface ListableOptions {
/** Output in JSON format */
json?: boolean;
/** Output in newline-delimited JSON format */
ndjson?: boolean;
/** Include private packages */
all?: boolean;
/** Show extended information */
long?: boolean;
/** Show parseable output for scripts */
parseable?: boolean;
/** Sort packages topologically */
toposort?: boolean;
/** Show dependency graph */
graph?: boolean;
}interface CommandConfigOptions {
/** Command line arguments */
_?: string[];
/** Number of concurrent processes */
concurrency?: number;
/** Sort packages topologically */
sort?: boolean;
/** Maximum buffer size for child processes */
maxBuffer?: number;
/** Stream output from child processes */
stream?: boolean;
/** Log level (silent, error, warn, info, verbose, silly) */
loglevel?: string;
/** Enable verbose logging */
verbose?: boolean;
/** Show progress bars */
progress?: boolean;
/** npm client to use (npm, yarn, pnpm) */
npmClient?: string;
/** Use Nx for task execution */
useNx?: boolean;
/** Independent versioning mode */
independent?: boolean;
/** CI environment flag */
ci?: boolean;
/** Use workspaces feature */
useWorkspaces?: boolean;
/** Git reference to compare against */
since?: string;
}
declare abstract class Command<T extends CommandConfigOptions = CommandConfigOptions> {
/** Command name */
name: string;
/** Whether command is composed of other commands */
composed: boolean;
/** Command options */
options: T;
/** Promise for command execution */
runner: Promise<unknown>;
/** Number of concurrent processes */
concurrency?: number;
/** Sort packages topologically */
toposort: boolean;
/** Execution options for child processes */
execOpts?: { cwd: string; maxBuffer?: number };
/** Package graph for dependency resolution */
packageGraph?: PackageGraph;
/** Logger instance */
logger: Logger;
/** Get project instance */
get project(): Project;
/** Set project instance */
set project(project: Project);
/** Whether command requires git repository */
get requiresGit(): boolean;
/** Configuration compatibility with other commands */
get otherCommandConfigs(): string[];
/** Initialize command */
abstract initialize(): void | boolean;
/** Execute command */
abstract execute(): void;
}
interface ExecutionOptions {
/** Current working directory */
cwd: string;
/** Maximum buffer size */
maxBuffer?: number;
}
interface Logger {
/** Log silly level message */
silly(prefix: string, message: string, ...args: any[]): void;
/** Log verbose level message */
verbose(prefix: string, message: string, ...args: any[]): void;
/** Log info level message */
info(prefix: string, message: string, ...args: any[]): void;
/** Log warn level message */
warn(prefix: string, message: string, ...args: any[]): void;
/** Log error level message */
error(prefix: string, message: string, ...args: any[]): void;
/** Log success level message */
success(prefix: string, message: string, ...args: any[]): void;
}
interface RawManifest {
name: string;
version: string;
private?: boolean;
bin?: Record<string, string> | string;
scripts?: Record<string, string>;
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
optionalDependencies?: Record<string, string>;
peerDependencies?: Record<string, string>;
publishConfig?: Record<"directory" | "registry" | "tag", string>;
workspaces?: string[];
}
declare class Package {
/** Package name */
name: string;
/** Package location on filesystem */
get location(): string;
/** Whether package is private */
get private(): boolean;
/** Package version */
get version(): string;
/** Package contents directory */
get contents(): string;
/** Package dependencies */
get dependencies(): Record<string, string> | undefined;
/** Package devDependencies */
get devDependencies(): Record<string, string> | undefined;
/** Package optionalDependencies */
get optionalDependencies(): Record<string, string> | undefined;
/** Package peerDependencies */
get peerDependencies(): Record<string, string> | undefined;
/** Set private flag */
set private(isPrivate: boolean);
/** Set package version */
set version(version: string);
/** Set contents directory */
set contents(subDirectory: string);
/** Create lazy package instance */
static lazy(ref: string | Package | RawManifest, dir?: string): Package;
/** Get manifest property */
get(key: keyof RawManifest): RawManifest[keyof RawManifest];
/** Set manifest property */
set(key: keyof RawManifest, val: RawManifest[keyof RawManifest]): Package;
/** Convert to JSON */
toJSON(): RawManifest;
/** Refresh package from filesystem */
refresh(): Promise<Package>;
/** Serialize package to filesystem */
serialize(): Promise<Package>;
/** Update local dependency */
updateLocalDependency(resolved: any, depVersion: string, savePrefix: string, options?: { retainWorkspacePrefix: boolean }): void;
/** Remove private field */
removePrivate(): void;
}
declare class PackageGraphNode {
/** Package name */
name: string;
/** External dependencies */
externalDependencies: Map<string, any>;
/** Local dependencies within monorepo */
localDependencies: Map<string, any>;
/** Local dependents within monorepo */
localDependents: Map<string, PackageGraphNode>;
/** Package location */
get location(): string;
/** Package instance */
get pkg(): Package;
/** Prerelease identifier */
get prereleaseId(): string;
/** Package version */
get version(): string;
/** Check if package satisfies dependency */
satisfies(spec: any): boolean;
/** String representation */
toString(): string;
}
declare class PackageGraph extends Map<string, PackageGraphNode> {
/** Raw list of packages */
get rawPackageList(): Package[];
/** Add dependencies to filtered packages */
addDependencies(filteredPackages: Package[]): Package[];
/** Add dependents to filtered packages */
addDependents(filteredPackages: Package[]): Package[];
/** Extend package list with related packages */
extendList(packageList: Package[], nodeProp: "localDependencies" | "localDependents"): Package[];
/** Partition cyclic dependencies */
partitionCycles(rejectCycles: boolean): [Set<string[]>, Set<PackageGraphNode>];
/** Collapse cyclic dependencies */
collapseCycles(rejectCycles?: boolean): Set<any>;
/** Remove cyclic nodes */
pruneCycleNodes(cycleNodes: Set<PackageGraphNode>): void;
/** Prune nodes from graph */
prune(...candidates: PackageGraphNode[]): void;
/** Remove specific node */
remove(candidateNode: PackageGraphNode): void;
}
declare class Project {
/** Project configuration */
config: any;
/** Whether config was found */
configNotFound: boolean;
/** Root config location */
rootConfigLocation: string;
/** Root path */
rootPath: string;
/** Project version */
get version(): string;
/** Set project version */
set version(val: string);
/** Package configurations */
get packageConfigs(): string[];
/** Package parent directories */
get packageParentDirs(): string[];
/** Root package manifest */
get manifest(): Package;
/** Get all packages */
getPackages(): Promise<Package[]>;
/** Get all packages synchronously */
getPackagesSync(): Package[];
/** Check if independent versioning */
isIndependent(): boolean;
/** Serialize configuration */
serializeConfig(): string;
}
/**
* Collect packages that have updates since last release
*/
declare function collectUpdates(
filteredPackages: Package[],
packageGraph: PackageGraph,
execOpts: ExecutionOptions,
commandOptions: any
): PackageGraphNode[];
/**
* Format package list for output
*/
declare function listableFormat(
pkgList: Package[],
options: ListableOptions
): {
text: string;
count: number;
};
/**
* Output text to console
*/
declare function output(...args: any[]): void;The package depends on:
collectUpdates, Command, listableFormat, output utilitiesprocess.exitCode = 1 for CLI usage when no packages changedThis package integrates with: