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.
npx @tessl/cli install tessl/npm-expo--package-manager@1.9.0@expo/package-manager provides 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. It offers a unified API for common package management operations while automatically detecting and adapting to the package manager used in a given project.
npm install @expo/package-managerimport * as PackageManager from '@expo/package-manager';For individual imports:
import { createForProject, PackageManager, NpmPackageManager } from '@expo/package-manager';CommonJS:
const PackageManager = require('@expo/package-manager');
const { createForProject } = require('@expo/package-manager');import { createForProject } from '@expo/package-manager';
// Automatically detect and create the appropriate package manager
const manager = createForProject('/path/to/project');
// Install dependencies
await manager.installAsync();
// Add production dependencies
await manager.addAsync(['express', 'lodash']);
// Add development dependencies
await manager.addDevAsync(['@types/node', 'typescript']);
// Remove dependencies
await manager.removeAsync(['unused-package']);
// Get package manager version
const version = await manager.versionAsync();@expo/package-manager is built around several key components:
PackageManager interface defining the standard contract for all package managersBasePackageManager abstract class providing common functionalityCocoaPodsPackageManager for iOS/macOS CocoaPods integrationCreate appropriate package managers automatically or explicitly based on project configuration and lockfiles.
function createForProject(
projectRoot: string,
options?: NodePackageManagerForProject
): NodePackageManager;
function resolvePackageManager(
projectRoot: string,
preferredManager?: NodePackageManager['name']
): NodePackageManager['name'] | null;
type NodePackageManagerForProject = PackageManagerOptions &
Partial<Record<NodePackageManager['name'], boolean>>;Implementations for npm, yarn, pnpm, and bun package managers with unified interface and package manager-specific optimizations.
interface PackageManager {
readonly options: PackageManagerOptions;
runAsync(command: string[], options?: SpawnOptions): SpawnPromise<SpawnResult>;
runBinAsync(command: string[], options?: SpawnOptions): SpawnPromise<SpawnResult>;
versionAsync(): Promise<string>;
installAsync(): Promise<SpawnResult> | SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
addAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
addDevAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
removeAsync(namesOrFlags: string[]): SpawnPromise<SpawnResult> | PendingSpawnPromise<SpawnResult>;
workspaceRoot(): PackageManager | null;
}
class NpmPackageManager extends BasePackageManager { }
class YarnPackageManager extends BasePackageManager { }
class PnpmPackageManager extends BasePackageManager { }
class BunPackageManager extends BasePackageManager { }iOS and macOS CocoaPods integration with automatic CLI installation, error handling, and project detection.
class CocoaPodsPackageManager {
static getPodProjectRoot(projectRoot: string): string | null;
static isUsingPods(projectRoot: string): boolean;
static installCLIAsync(options: {
nonInteractive?: boolean;
spawnOptions?: SpawnOptions;
}): Promise<boolean>;
installAsync(options?: { spinner?: Ora }): Promise<void>;
versionAsync(): Promise<string>;
}Workspace detection, offline support, environment detection, and advanced promise utilities.
function resolveWorkspaceRoot(projectRoot: string): string | null;
function isYarnOfflineAsync(): Promise<boolean>;
interface PendingSpawnPromise<T> extends Promise<T> {
child: Promise<SpawnPromise<T>['child'] | null>;
}
function createPendingSpawnAsync<V, T>(
actionAsync: () => Promise<V>,
spawnAsync: (result: V) => SpawnPromise<T>
): PendingSpawnPromise<T>;interface PackageManagerOptions extends SpawnOptions {
/** If the package manager should run in silent mode */
silent?: boolean;
/** The logging method used to communicate executed commands */
log?: (...args: any[]) => void;
}
type NodePackageManager =
| NpmPackageManager
| PnpmPackageManager
| YarnPackageManager
| BunPackageManager;
type CocoaPodsErrorCode = 'NON_INTERACTIVE' | 'NO_CLI' | 'COMMAND_FAILED';
class CocoaPodsError extends Error {
readonly name = 'CocoaPodsError';
readonly isPackageManagerError = true;
constructor(message: string, public code: CocoaPodsErrorCode, public cause?: Error);
}const NPM_LOCK_FILE = 'package-lock.json';
const YARN_LOCK_FILE = 'yarn.lock';
const PNPM_LOCK_FILE = 'pnpm-lock.yaml';
const BUN_LOCK_FILE = 'bun.lockb';
const BUN_TEXT_LOCK_FILE = 'bun.lock';
const RESOLUTION_ORDER: NodePackageManager['name'][] = ['bun', 'yarn', 'npm', 'pnpm'];