A comprehensive cross-platform package management abstraction library that enables developers to programmatically install, manage, and find packages across multiple package managers including npm, yarn, pnpm, bun for Node.js projects, and CocoaPods for iOS projects.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Unified interface and implementations for npm, yarn, pnpm, and bun package managers with package manager-specific optimizations and consistent API.
All Node.js package managers implement the core PackageManager interface.
interface PackageManager {
/** The options for this package manager */
readonly options: PackageManagerOptions;
/** Run any command using the package manager */
runAsync(command: string[], options?: SpawnOptions): SpawnPromise<SpawnResult>;
/** Invoke a binary from within a package, like "eslint" or "jest" */
runBinAsync(command: string[], options?: SpawnOptions): SpawnPromise<SpawnResult>;
/** Get the version of the used package manager */
versionAsync(): Promise<string>;
/** Get a single configuration property from the package manager */
getConfigAsync(key: string): Promise<string>;
/** Remove the lock file within the project, if any */
removeLockfileAsync(): Promise<void>;
/** Get the workspace root package manager, if this project is within a workspace/monorepo */
workspaceRoot(): PackageManager | null;
/** Install all current dependencies using the package manager */
installAsync(): Promise<SpawnResult> | SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
/** Uninstall all current dependencies by removing the folder containing the packages */
uninstallAsync(): Promise<void>;
/** Add a normal dependency to the project */
addAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
/** Add a development dependency to the project */
addDevAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
/** Add a global dependency to the environment */
addGlobalAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
/** Remove a normal dependency from the project */
removeAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
/** Remove a development dependency from the project */
removeDevAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
/** Remove a global dependency from the environments */
removeGlobalAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
}
interface PackageManagerOptions extends SpawnOptions {
/** If the package manager should run in silent mode */
silent?: boolean;
/** The logging method used to communicate the command which is executed */
log?: (...args: any[]) => void;
}Abstract base class providing common functionality for all Node.js package managers.
abstract class BasePackageManager implements PackageManager {
readonly silent: boolean;
readonly log?: (...args: any) => void;
readonly options: PackageManagerOptions;
/** Get the name of the package manager */
abstract readonly name: string;
/** Get the executable binary of the package manager */
abstract readonly bin: string;
/** Get the lockfile for this package manager */
abstract readonly lockFile: string;
constructor(options?: PackageManagerOptions);
runAsync(command: string[], options?: SpawnOptions): SpawnPromise<SpawnResult>;
runBinAsync(command: string[], options?: SpawnOptions): SpawnPromise<SpawnResult>;
versionAsync(): Promise<string>;
getConfigAsync(key: string): Promise<string>;
removeLockfileAsync(): Promise<void>;
installAsync(flags?: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
uninstallAsync(): Promise<void>;
}Implementation for npm package manager with npm-specific optimizations.
class NpmPackageManager extends BasePackageManager {
readonly name = 'npm';
readonly bin = 'npm';
readonly lockFile = 'package-lock.json';
workspaceRoot(): NpmPackageManager | null;
addAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
addDevAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
addGlobalAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
removeAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeDevAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeGlobalAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
runBinAsync(command: string[], options?: SpawnOptions): SpawnPromise<SpawnResult>;
}Usage Examples:
import { NpmPackageManager } from '@expo/package-manager';
const npm = new NpmPackageManager({ cwd: '/path/to/project' });
// Install dependencies
await npm.installAsync();
// Add packages with version specifications
await npm.addAsync(['express@^4.18.0', 'lodash']);
// Use npx to run binaries
await npm.runBinAsync(['typescript', '--version']);Implementation for Yarn package manager with offline support and workspace detection.
class YarnPackageManager extends BasePackageManager {
readonly name = 'yarn';
readonly bin = 'yarnpkg';
readonly lockFile = 'yarn.lock';
workspaceRoot(): YarnPackageManager | null;
installAsync(flags?: string[]): PendingSpawnPromise<SpawnResult>;
addAsync(namesOrFlags?: string[]): PendingSpawnPromise<SpawnResult>;
addDevAsync(namesOrFlags?: string[]): PendingSpawnPromise<SpawnResult>;
addGlobalAsync(namesOrFlags?: string[]): PendingSpawnPromise<SpawnResult>;
removeAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeDevAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeGlobalAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
}Usage Examples:
import { YarnPackageManager } from '@expo/package-manager';
const yarn = new YarnPackageManager({ cwd: '/path/to/project' });
// Yarn automatically handles offline mode
await yarn.installAsync();
// Add development dependencies
await yarn.addDevAsync(['@types/node', 'typescript']);
// Global package management
await yarn.addGlobalAsync(['nodemon']);
await yarn.removeGlobalAsync(['old-global-package']);Implementation for pnpm package manager with CI-specific optimizations.
class PnpmPackageManager extends BasePackageManager {
readonly name = 'pnpm';
readonly bin = 'pnpm';
readonly lockFile = 'pnpm-lock.yaml';
workspaceRoot(): PnpmPackageManager | null;
installAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
addAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
addDevAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
addGlobalAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
removeAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeDevAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeGlobalAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
}Usage Examples:
import { PnpmPackageManager } from '@expo/package-manager';
const pnpm = new PnpmPackageManager({ cwd: '/path/to/project' });
// In CI, automatically adds --no-frozen-lockfile if not specified
await pnpm.installAsync();
// Standard dependency management
await pnpm.addAsync(['fastify', 'zod']);
await pnpm.removeAsync(['unused-package']);Implementation for Bun package manager.
class BunPackageManager extends BasePackageManager {
readonly name = 'bun';
readonly bin = 'bun';
readonly lockFile = 'bun.lockb';
workspaceRoot(): BunPackageManager | null;
installAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
addAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
addDevAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
addGlobalAsync(namesOrFlags?: string[]): SpawnPromise<SpawnResult>;
removeAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeDevAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
removeGlobalAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult>;
}Usage Examples:
import { BunPackageManager } from '@expo/package-manager';
const bun = new BunPackageManager({ cwd: '/path/to/project' });
// Fast installation with Bun
await bun.installAsync();
// Add packages
await bun.addAsync(['hono', '@types/bun']);
// Development dependencies
await bun.addDevAsync(['bun-types']);Workspace Management:
// Get workspace root manager
const rootManager = manager.workspaceRoot();
if (rootManager) {
// Install at workspace root
await rootManager.installAsync();
}Configuration Access:
// Get package manager configuration
const registry = await manager.getConfigAsync('registry');
const version = await manager.versionAsync();Cleanup Operations:
// Remove dependencies and clean up
await manager.removeAsync(['old-package']);
await manager.removeLockfileAsync();
await manager.uninstallAsync(); // Removes node_modulesRunning Commands:
// Run package manager commands
await manager.runAsync(['audit', 'fix']);
// Run package binaries
await manager.runBinAsync(['eslint', 'src/']);type NodePackageManager =
| NpmPackageManager
| PnpmPackageManager
| YarnPackageManager
| BunPackageManager;