Find all packages inside a directory using glob patterns with intelligent filtering
npx @tessl/cli install tessl/npm-pnpm-fs--find-packages@1000.0.0@pnpm/fs.find-packages is a TypeScript library that discovers and locates package.json files within directory structures. It uses intelligent glob patterns to search through directories while filtering out common non-package locations, making it essential for build tools, package managers, and workspace management systems.
npm install @pnpm/fs.find-packagesimport { findPackages, type Options } from "@pnpm/fs.find-packages";For CommonJS:
const { findPackages } = require("@pnpm/fs.find-packages");import { findPackages } from "@pnpm/fs.find-packages";
// Find all packages in a directory
const packages = await findPackages("/path/to/workspace");
// Find packages with custom patterns
const packages = await findPackages("/path/to/workspace", {
patterns: ["components/**", "libs/**"],
ignore: ["**/test/**"]
});
// Access package information
packages.forEach(pkg => {
console.log(`Found package: ${pkg.manifest.name} at ${pkg.rootDir}`);
});Finds all packages in a directory using glob patterns with intelligent filtering for common non-package locations.
/**
* Find all packages inside a directory
* @param root - The directory to search for packages
* @param opts - Optional configuration options
* @returns Promise resolving to array of discovered projects
*/
export function findPackages(root: string, opts?: Options): Promise<Project[]>;
export interface Options {
/** Custom patterns to ignore when searching (overrides defaults) */
ignore?: string[];
/** Whether to include the workspace root in results */
includeRoot?: boolean;
/** Custom glob patterns for package locations (default: ['.', '**']) */
patterns?: string[];
}Usage Examples:
import { findPackages, type Options } from "@pnpm/fs.find-packages";
// Find all packages using default patterns (searches '.' and '**')
const allPackages = await findPackages("/path/to/monorepo");
console.log(`Found ${allPackages.length} packages`);
// Find packages in specific directories only
const componentPackages = await findPackages("/path/to/workspace", {
patterns: ["components/**"]
});
// Find packages using wildcard patterns
const specificPackages = await findPackages("/path/to/workspace", {
patterns: [".", "components/*"] // Include root and direct subdirs of components
});
// Find packages with custom ignore patterns
const filteredPackages = await findPackages("/path/to/workspace", {
patterns: ["**"],
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**", "**/test/**"]
});
// Include workspace root as a package (useful for monorepo root)
const withRoot = await findPackages("/path/to/workspace", {
includeRoot: true
});
// Exclude specific directories using negation patterns
const excludeLibs = await findPackages("/path/to/workspace", {
patterns: ["**", "!libs/**"] // Find all except libs directory
});
// Exclude from root level only (different from general exclusion)
const excludeRootLibs = await findPackages("/path/to/workspace", {
patterns: ["**", "!/libs/**"] // Exclude libs at root level only
});
// Access package information
allPackages.forEach(pkg => {
console.log(`Package: ${pkg.manifest.name}`);
console.log(`Version: ${pkg.manifest.version}`);
console.log(`Location: ${pkg.rootDir}`);
console.log(`Real path: ${pkg.rootDirRealPath}`);
// Check if it has dependencies
if (pkg.manifest.dependencies) {
console.log(`Dependencies: ${Object.keys(pkg.manifest.dependencies).join(', ')}`);
}
// Write updated manifest if needed
// pkg.writeProjectManifest({ ...pkg.manifest, version: '2.0.0' });
});/** Configuration options for findPackages function */
interface Options {
/**
* Patterns to ignore when searching for packages
* Default: ['**/node_modules/**', '**/bower_components/**', '**/test/**', '**/tests/**']
*/
ignore?: string[];
/** Whether to include the workspace root directory as a package */
includeRoot?: boolean;
/**
* Glob patterns to use as package locations
* Default: ['.', '**'] (searches current directory and all subdirectories)
*/
patterns?: string[];
}
/** Represents a discovered package project */
interface Project {
/** Project root directory path */
rootDir: ProjectRootDir;
/** Real path to project root (resolved symlinks) */
rootDirRealPath: ProjectRootDirRealPath;
/** Optional modules directory path */
modulesDir?: string;
/** Package manifest data (package.json contents) */
manifest: ProjectManifest;
/** Function to write updated manifest to disk */
writeProjectManifest: (manifest: ProjectManifest, force?: boolean) => Promise<void>;
}
/** Branded string type for project root directory paths */
type ProjectRootDir = string & { __brand: 'ProjectRootDir' };
/** Branded string type for real project root directory paths */
type ProjectRootDirRealPath = string & { __brand: 'ProjectRootDirRealPath' };
/** Package dependencies mapping */
type Dependencies = Record<string, string>;
/** Package bin configuration */
type PackageBin = string | { [commandName: string]: string };
/** Package scripts configuration with known lifecycle hooks */
type PackageScripts = {
[name: string]: string;
} & {
prepublish?: string;
prepare?: string;
prepublishOnly?: string;
prepack?: string;
postpack?: string;
publish?: string;
postpublish?: string;
preinstall?: string;
install?: string;
postinstall?: string;
preuninstall?: string;
uninstall?: string;
postuninstall?: string;
preversion?: string;
version?: string;
postversion?: string;
pretest?: string;
test?: string;
posttest?: string;
prestop?: string;
stop?: string;
poststop?: string;
prestart?: string;
start?: string;
poststart?: string;
prerestart?: string;
restart?: string;
postrestart?: string;
preshrinkwrap?: string;
shrinkwrap?: string;
postshrinkwrap?: string;
};
/** Peer dependencies metadata */
interface PeerDependenciesMeta {
[dependencyName: string]: {
optional?: boolean;
};
}
/** Dependencies metadata for custom configuration */
interface DependenciesMeta {
[dependencyName: string]: {
injected?: boolean;
node?: string;
patch?: string;
};
}
/** Development engine dependency configuration */
interface DevEngineDependency {
name: string;
version?: string;
onFail?: 'ignore' | 'warn' | 'error' | 'download';
}
/** Development engines configuration */
interface DevEngines {
os?: DevEngineDependency | DevEngineDependency[];
cpu?: DevEngineDependency | DevEngineDependency[];
libc?: DevEngineDependency | DevEngineDependency[];
runtime?: DevEngineDependency | DevEngineDependency[];
packageManager?: DevEngineDependency | DevEngineDependency[];
}
/** Publish configuration */
interface PublishConfig extends Record<string, unknown> {
directory?: string;
linkDirectory?: boolean;
executableFiles?: string[];
registry?: string;
}
/** TypeScript types versions mapping */
interface TypesVersions {
[version: string]: {
[pattern: string]: string[];
};
}
/** Peer dependency rules configuration */
interface PeerDependencyRules {
ignoreMissing?: string[];
allowAny?: string[];
allowedVersions?: Record<string, string>;
}
/** Audit configuration */
interface AuditConfig {
ignoreCves?: string[];
ignoreGhsas?: string[];
}
/** Supported architectures configuration */
interface SupportedArchitectures {
os?: string[];
cpu?: string[];
libc?: string[];
}
/** pnpm-specific settings */
interface PnpmSettings {
configDependencies?: Record<string, string>;
neverBuiltDependencies?: string[];
onlyBuiltDependencies?: string[];
onlyBuiltDependenciesFile?: string;
ignoredBuiltDependencies?: string[];
overrides?: Record<string, string>;
packageExtensions?: Record<string, any>;
ignoredOptionalDependencies?: string[];
peerDependencyRules?: PeerDependencyRules;
allowedDeprecatedVersions?: Record<string, string>;
allowNonAppliedPatches?: boolean;
allowUnusedPatches?: boolean;
ignorePatchFailures?: boolean;
patchedDependencies?: Record<string, string>;
updateConfig?: {
ignoreDependencies?: string[];
};
auditConfig?: AuditConfig;
requiredScripts?: string[];
supportedArchitectures?: SupportedArchitectures;
}
/** Complete package manifest data structure (package.json contents) */
interface ProjectManifest {
name?: string;
version?: string;
type?: string;
bin?: PackageBin;
description?: string;
directories?: {
bin?: string;
};
files?: string[];
funding?: string;
dependencies?: Dependencies;
devDependencies?: Dependencies;
optionalDependencies?: Dependencies;
peerDependencies?: Dependencies;
peerDependenciesMeta?: PeerDependenciesMeta;
dependenciesMeta?: DependenciesMeta;
bundleDependencies?: string[] | boolean;
bundledDependencies?: string[] | boolean;
homepage?: string;
repository?: string | { url: string };
bugs?: string | {
url?: string;
email?: string;
};
scripts?: PackageScripts;
config?: object;
engines?: {
node?: string;
npm?: string;
pnpm?: string;
};
devEngines?: DevEngines;
cpu?: string[];
os?: string[];
libc?: string[];
main?: string;
module?: string;
typings?: string;
types?: string;
publishConfig?: PublishConfig;
typesVersions?: TypesVersions;
readme?: string;
keywords?: string[];
author?: string;
license?: string;
exports?: Record<string, string>;
imports?: Record<string, unknown>;
packageManager?: string;
workspaces?: string[];
pnpm?: PnpmSettings;
private?: boolean;
resolutions?: Record<string, string>;
}By default, the following patterns are ignored to avoid scanning non-package directories:
**/node_modules/** - Node.js dependencies**/bower_components/** - Bower dependencies**/test/** - Test directories**/tests/** - Test directories (plural)The function handles common filesystem errors gracefully:
Glob patterns follow standard glob syntax with these behaviors:
** matches any number of directories recursively* matches any characters except directory separators!pattern excludes matches from the pattern!/pattern (with leading slash) excludes from root level only/package.{json,yaml,json5})All patterns are automatically normalized by appending /package.{json,yaml,json5} to search for package manifest files. This means:
"." becomes "./package.{json,yaml,json5}" (searches current directory)"**" becomes "**/package.{json,yaml,json5}" (searches all subdirectories)"components/**" becomes "components/**/package.{json,yaml,json5}"If no patterns are specified, the default patterns ['.', '**'] are used, which searches:
The library automatically searches for packages using any of these manifest file formats:
package.json - Standard JSON formatpackage.yaml - YAML formatpackage.json5 - JSON5 format with comments and trailing commas